Full Code of kitojs/kito for AI

main 33b3c40ef365 cached
179 files
325.7 KB
87.6k tokens
408 symbols
1 requests
Download .txt
Showing preview only (367K chars total). Download the full file or copy to clipboard to get everything.
Repository: kitojs/kito
Branch: main
Commit: 33b3c40ef365
Files: 179
Total size: 325.7 KB

Directory structure:
gitextract_l4urthhv/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   └── workflows/
│       ├── ci.yml
│       ├── doc-deploy.yml
│       └── release.yml
├── .gitignore
├── Cargo.toml
├── bench/
│   ├── cases/
│   │   └── basic/
│   │       ├── elysia.ts
│   │       ├── express.ts
│   │       ├── fastify.ts
│   │       ├── hapi.ts
│   │       ├── hono.ts
│   │       ├── kito.ts
│   │       ├── koa.ts
│   │       ├── restify.ts
│   │       └── tinyhttp.ts
│   ├── config.ts
│   ├── package.json
│   ├── readme.md
│   ├── results/
│   │   ├── comparison-bun.json
│   │   ├── comparison-node.json
│   │   └── data/
│   │       ├── bun/
│   │       │   ├── elysia.json
│   │       │   ├── express.json
│   │       │   ├── fastify.json
│   │       │   ├── hapi.json
│   │       │   ├── hono.json
│   │       │   ├── kito.json
│   │       │   ├── koa.json
│   │       │   └── tinyhttp.json
│   │       └── node/
│   │           ├── elysia.json
│   │           ├── express.json
│   │           ├── fastify.json
│   │           ├── hapi.json
│   │           ├── hono.json
│   │           ├── kito.json
│   │           ├── koa.json
│   │           ├── restify.json
│   │           └── tinyhttp.json
│   ├── runBench.ts
│   ├── tsconfig.json
│   └── utils/
│       ├── chart.ts
│       ├── frameworkRunner.ts
│       ├── http.ts
│       └── wait.ts
├── biome.json
├── cli/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── install.js
│   ├── package.json
│   └── src/
│       ├── commands.rs
│       ├── main.rs
│       └── utils.rs
├── cliff.toml
├── examples/
│   ├── fluent/
│   │   ├── basic.ts
│   │   ├── clustering/
│   │   │   ├── index.ts
│   │   │   └── server.ts
│   │   ├── extend.ts
│   │   ├── file.ts
│   │   ├── middlewares/
│   │   │   ├── index.ts
│   │   │   └── samples/
│   │   │       ├── auth.ts
│   │   │       └── logger.ts
│   │   ├── params.ts
│   │   ├── route.ts
│   │   ├── router/
│   │   │   ├── cats.ts
│   │   │   └── index.ts
│   │   ├── schemas/
│   │   │   ├── builder.ts
│   │   │   └── json.ts
│   │   ├── streaming/
│   │   │   ├── sse.ts
│   │   │   └── stream.ts
│   │   └── unixSocket.ts
│   ├── instance/
│   │   ├── basic.ts
│   │   ├── clustering/
│   │   │   ├── index.ts
│   │   │   └── server.ts
│   │   ├── extend.ts
│   │   ├── file.ts
│   │   ├── middlewares/
│   │   │   ├── index.ts
│   │   │   └── samples/
│   │   │       ├── auth.ts
│   │   │       └── logger.ts
│   │   ├── params.ts
│   │   ├── route.ts
│   │   ├── router/
│   │   │   ├── cats.ts
│   │   │   └── index.ts
│   │   ├── schemas/
│   │   │   ├── builder.ts
│   │   │   └── json.ts
│   │   ├── streaming/
│   │   │   ├── sse.ts
│   │   │   └── stream.ts
│   │   └── unixSocket.ts
│   ├── package.json
│   ├── runExample.ts
│   └── tsconfig.json
├── lefthook.yml
├── license
├── package.json
├── packages/
│   ├── core/
│   │   ├── .gitignore
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── http/
│   │   │   │   ├── cookies.rs
│   │   │   │   ├── cookies_tests.rs
│   │   │   │   ├── files.rs
│   │   │   │   ├── mime.rs
│   │   │   │   ├── mime_tests.rs
│   │   │   │   ├── request.rs
│   │   │   │   └── response.rs
│   │   │   ├── http.rs
│   │   │   ├── lib.rs
│   │   │   ├── server/
│   │   │   │   ├── context.rs
│   │   │   │   ├── core.rs
│   │   │   │   ├── handler.rs
│   │   │   │   ├── router.rs
│   │   │   │   └── routes.rs
│   │   │   ├── server.rs
│   │   │   ├── validation/
│   │   │   │   ├── parser.rs
│   │   │   │   ├── parser_tests.rs
│   │   │   │   ├── tests.rs
│   │   │   │   ├── types.rs
│   │   │   │   └── validators.rs
│   │   │   └── validation.rs
│   │   └── tsconfig.json
│   ├── kitojs/
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── readme.md
│   │   ├── src/
│   │   │   ├── helpers/
│   │   │   │   ├── middleware.ts
│   │   │   │   └── schema.ts
│   │   │   ├── index.ts
│   │   │   ├── schemas/
│   │   │   │   ├── builders.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── jsonSchema.ts
│   │   │   │   └── primitives/
│   │   │   │       ├── array.ts
│   │   │   │       ├── boolean.ts
│   │   │   │       ├── literal.ts
│   │   │   │       ├── number.ts
│   │   │   │       ├── object.ts
│   │   │   │       ├── string.ts
│   │   │   │       └── union.ts
│   │   │   ├── server/
│   │   │   │   ├── analyzer.ts
│   │   │   │   ├── request.ts
│   │   │   │   ├── response.ts
│   │   │   │   ├── router.ts
│   │   │   │   └── server.ts
│   │   │   └── types.ts
│   │   ├── tests/
│   │   │   ├── analyzer.test.ts
│   │   │   ├── middleware.test.ts
│   │   │   ├── route-chain.test.ts
│   │   │   ├── router.test.ts
│   │   │   ├── schema-helper.test.ts
│   │   │   ├── server.test.ts
│   │   │   └── types.test.ts
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   ├── typedoc.json
│   │   └── vitest.config.ts
│   ├── readme.md
│   └── types/
│       ├── .gitignore
│       ├── package.json
│       ├── src/
│       │   ├── context.d.ts
│       │   ├── handlers.d.ts
│       │   ├── http/
│       │   │   ├── request.d.ts
│       │   │   └── response.d.ts
│       │   ├── index.d.ts
│       │   ├── router.d.ts
│       │   ├── routes.d.ts
│       │   ├── schema/
│       │   │   ├── array.d.ts
│       │   │   ├── base.d.ts
│       │   │   ├── boolean.d.ts
│       │   │   ├── jsonSchema.d.ts
│       │   │   ├── literal.d.ts
│       │   │   ├── number.d.ts
│       │   │   ├── object.d.ts
│       │   │   ├── string.d.ts
│       │   │   └── union.d.ts
│       │   └── server.d.ts
│       ├── tsconfig.json
│       └── tsdown.config.ts
├── pnpm-workspace.yaml
├── readme.md
├── rust-toolchain.toml
├── rustfmt.toml
└── tsconfig.base.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: Report a problem or unexpected behavior in the project
title: "[Bug]: "
labels: ["bug"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to report a bug!

  - type: input
    id: version
    attributes:
      label: Version
      description: What version are you using?
      placeholder: e.g. 1.0.0-alpha.4
    validations:
      required: true

  - type: textarea
    id: description
    attributes:
      label: Description of the issue
      description: Explain what happened and what you expected to happen
      placeholder: "Describe the bug here"
    validations:
      required: true

  - type: textarea
    id: steps
    attributes:
      label: Steps to reproduce
      description: Provide steps so we can reproduce the issue
      placeholder: |
        1. Run ...
        2. Call ...
        3. Observe ...
    validations:
      required: true

  - type: textarea
    id: logs
    attributes:
      label: Logs or error messages
      description: Paste any relevant logs, stack traces, or console output
      render: shell

  - type: textarea
    id: environment
    attributes:
      label: Environment
      description: Describe your environment
      placeholder: |
        OS:
        Runtime (Node/Bun/Deno):
        CPU:
        Additional details:

  - type: checkboxes
    id: checklist
    attributes:
      label: Checklist
      options:
        - label: I have searched existing issues
        - label: I am using the latest version


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Suggest a new idea or improvement
title: "[Feature]: "
labels: ["enhancement"]
body:
  - type: textarea
    id: summary
    attributes:
      label: Summary
      description: Briefly describe the feature you'd like to see
    validations:
      required: true

  - type: textarea
    id: motivation
    attributes:
      label: Motivation
      description: Why is this feature important? What problem does it solve?
    validations:
      required: true

  - type: textarea
    id: proposal
    attributes:
      label: Proposed Solution
      description: Describe how this feature could be implemented or how you'd expect it to behave

  - type: checkboxes
    id: checklist
    attributes:
      label: Checklist
      options:
        - label: I've searched for related issues
        - label: I've read the documentation


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [main, dev]
  pull_request:
    branches: [main, dev]

jobs:
  lint-and-test:
    name: Lint & Test
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 8

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v4
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install -r

      - name: Build
        run: pnpm build

      - name: Test TypeScript
        run: pnpm test
        working-directory: packages/kitojs

  rust-test:
    name: Rust Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: stable

      - name: Cache Rust dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            packages/core/target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-

      - name: Run Rust tests
        run: cargo test --verbose
        working-directory: packages/core

      - name: Check Rust formatting
        run: cargo fmt -- --check
        working-directory: packages/core

      - name: Run Clippy
        run: cargo clippy -- -D warnings
        working-directory: packages/core

================================================
FILE: .github/workflows/doc-deploy.yml
================================================
name: Deploy Docs

on:
  push:
    branches: [main]
    paths:
      - 'packages/kitojs/src/**'
      - 'packages/types/src/**'
  workflow_dispatch:

jobs:
  deploy-docs:
    name: Generate and Deploy API Docs
    runs-on: ubuntu-latest

    steps:
      - name: Checkout kito repo
        uses: actions/checkout@v4
        with:
          path: kito

      - name: Checkout web repo
        uses: actions/checkout@v4
        with:
          repository: kitojs/web
          token: ${{ secrets.WEB_REPO_TOKEN }}
          path: web

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 8

      - name: Install kito dependencies
        run: pnpm install -r --ignore-scripts
        working-directory: kito

      - name: Build kito packages
        run: pnpm build
        working-directory: kito

      - name: Install TypeDoc in kitojs package
        run: pnpm add -D typedoc
        working-directory: kito/packages/kitojs
        
      - name: Generate TypeDoc
        working-directory: kito
        run: |
          cd packages/kitojs
          pnpm exec typedoc

      - name: Copy docs to web repo
        run: |
          # Remove old API docs if they exist
          rm -rf web/public/api
          
          # Copy new generated docs
          mkdir -p web/public/api
          cp -r kito/packages/kitojs/docs/* web/public/api/
          
          # Verify files were copied
          ls -la web/public/api/

      - name: Commit and push to web repo
        working-directory: web
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          
          git add public/api
          
          if git diff --staged --quiet; then
            echo "No changes to commit"
          else
            git commit -m "docs: update API documentation"
            git push
          fi

================================================
FILE: .github/workflows/release.yml
================================================
name: Release

permissions:
  contents: write
  packages: write

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:

jobs:
  build-napi:
    name: Build NAPI - ${{ matrix.settings.target }}
    strategy:
      fail-fast: false
      matrix:
        settings:
          - host: macos-latest
            target: x86_64-apple-darwin
            build: pnpm core:build --target x86_64-apple-darwin
          - host: macos-latest
            target: aarch64-apple-darwin
            build: pnpm core:build --target aarch64-apple-darwin
          - host: windows-latest
            target: x86_64-pc-windows-msvc
            build: pnpm core:build --target x86_64-pc-windows-msvc
          - host: windows-latest
            target: i686-pc-windows-msvc
            build: pnpm core:build --target i686-pc-windows-msvc
          - host: windows-latest
            target: aarch64-pc-windows-msvc
            build: pnpm core:build --target aarch64-pc-windows-msvc
          - host: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            build: pnpm core:build --target x86_64-unknown-linux-gnu --use-napi-cross
          - host: ubuntu-latest
            target: x86_64-unknown-linux-musl
            build: pnpm core:build --target x86_64-unknown-linux-musl -x
          - host: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            build: pnpm core:build --target aarch64-unknown-linux-gnu --use-napi-cross
          - host: ubuntu-latest
            target: aarch64-unknown-linux-musl
            build: pnpm core:build --target aarch64-unknown-linux-musl -x
          - host: ubuntu-latest
            target: armv7-unknown-linux-gnueabihf
            build: pnpm core:build --target armv7-unknown-linux-gnueabihf --use-napi-cross
    runs-on: ${{ matrix.settings.host }}
    steps:
      - uses: actions/checkout@v5

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 8

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          targets: ${{ matrix.settings.target }}
          components: clippy, rustfmt

      - name: Install build dependencies (Linux only)
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential musl-tools clang pkg-config libssl-dev

      - name: Setup zig (required for musl / cargo-zigbuild)
        if: ${{ contains(matrix.settings.target, 'musl') }}
        uses: mlugg/setup-zig@v2
        with:
          version: '0.15.2'

      - name: Install cargo-zigbuild (musl only)
        if: ${{ contains(matrix.settings.target, 'musl') }}
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-zigbuild
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Install dependencies
        run: pnpm install -r

      - name: Build NAPI binary
        run: ${{ matrix.settings.build }}
        working-directory: .
        shell: bash

      - name: List built files
        run: ls -la packages/core/dist/
        shell: bash

      - name: Upload artifact
        uses: actions/upload-artifact@v5
        with:
          name: bindings-${{ matrix.settings.target }}
          path: packages/core/dist/*.node
          if-no-files-found: error

  build-freebsd:
    runs-on: ubuntu-latest
    name: Build NAPI - FreeBSD
    steps:
      - uses: actions/checkout@v5
      
      - name: Build on FreeBSD
        id: build
        uses: cross-platform-actions/action@v0.30.0
        env:
          DEBUG: napi:*
          RUSTUP_IO_THREADS: 1
        with:
          operating_system: freebsd
          version: '14.3'
          memory: 8G
          cpu_count: 3
          environment_variables: 'DEBUG RUSTUP_IO_THREADS'
          shell: bash
          run: |
            sudo pkg install -y -f curl node libnghttp2 npm
            sudo npm install -g corepack
            curl https://sh.rustup.rs -sSf --output rustup.sh
            sh rustup.sh -y --profile minimal --default-toolchain stable
            sudo corepack enable
            source "$HOME/.cargo/env"
            echo "~~~~ rustc --version ~~~~"
            rustc --version
            echo "~~~~ node -v ~~~~"
            node -v
            echo "~~~~ pnpm --version ~~~~"
            pnpm --version
            pwd
            ls -lah
            whoami
            env
            freebsd-version
            pnpm install -r --filter '!bench' --filter '!examples'
            pnpm core:build
            rm -rf node_modules
            rm -rf target
      
      - name: Upload artifact
        uses: actions/upload-artifact@v5
        with:
          name: bindings-x86_64-unknown-freebsd
          path: packages/core/dist/*.node
          if-no-files-found: error

  publish-npm:
    name: Publish to NPM
    runs-on: ubuntu-latest
    needs: 
      - build-napi
      - build-freebsd

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 8

      - name: Install dependencies
        run: pnpm install -r

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: List all downloaded artifacts
        run: |
          echo "-- Downloaded artifacts structure --"
          ls -laR artifacts/

      - name: Create dist directory for core
        run: mkdir -p packages/core/dist

      - name: Move all .node binaries to core dist
        run: |
          echo "-- Moving .node files --"
          for artifact_dir in artifacts/bindings-*; do
            if [ -d "$artifact_dir" ]; then
              target=$(basename "$artifact_dir" | sed 's/^bindings-//')
              echo "Processing target: $target"

              node_file=$(find "$artifact_dir" -name "*.node" -type f)
              if [ -n "$node_file" ]; then
                case "$target" in
                  x86_64-apple-darwin)
                    dest_name="core.darwin-x64.node"
                    ;;
                  aarch64-apple-darwin)
                    dest_name="core.darwin-arm64.node"
                    ;;
                  x86_64-pc-windows-msvc)
                    dest_name="core.win32-x64-msvc.node"
                    ;;
                  i686-pc-windows-msvc)
                    dest_name="core.win32-ia32-msvc.node"
                    ;;
                  aarch64-pc-windows-msvc)
                    dest_name="core.win32-arm64-msvc.node"
                    ;;
                  x86_64-unknown-linux-gnu)
                    dest_name="core.linux-x64-gnu.node"
                    ;;
                  x86_64-unknown-linux-musl)
                    dest_name="core.linux-x64-musl.node"
                    ;;
                  aarch64-unknown-linux-gnu)
                    dest_name="core.linux-arm64-gnu.node"
                    ;;
                  aarch64-unknown-linux-musl)
                    dest_name="core.linux-arm64-musl.node"
                    ;;
                  armv7-unknown-linux-gnueabihf)
                    dest_name="core.linux-arm-gnueabihf.node"
                    ;;
                  x86_64-unknown-freebsd)
                    dest_name="core.freebsd-x64.node"
                    ;;
                  *)
                    echo "Warning: Unknown target $target, using generic name"
                    dest_name="core.$target.node"
                    ;;
                esac
                
                echo "  Copying: $node_file -> packages/core/dist/$dest_name"
                cp -v "$node_file" "packages/core/dist/$dest_name"
              else
                echo "  Warning: No .node file found in $artifact_dir"
              fi
            fi
          done
          echo "-- Final dist contents --"
          ls -la packages/core/dist/

      - name: Build NAPI index files
        run: |
          cd packages/core
          pnpm napi build --platform --release --esm --const-enum --output-dir dist
        shell: bash

      - name: Verify core package structure
        run: |
          echo "-- Core package dist/ contents --"
          ls -la packages/core/dist/
          echo "-- Checking for required files --"
          test -f packages/core/dist/index.js && echo "✓ index.js found" || echo "✗ index.js missing"
          test -f packages/core/dist/index.d.ts && echo "✓ index.d.ts found" || echo "✗ index.d.ts missing"
          echo "-- .node files --"
          find packages/core/dist/ -name "*.node" -exec basename {} \;

      - name: Build TypeScript packages
        run: pnpm ts:build

      - name: Publish @kitojs/kito-core
        run: pnpm publish --access public --no-git-checks
        working-directory: packages/core
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Publish @kitojs/types
        run: pnpm publish --access public --no-git-checks
        working-directory: packages/types
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Publish kitojs
        run: pnpm publish --access public --no-git-checks
        working-directory: packages/kitojs
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  create-release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: publish-npm

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Extract version from tag
        id: version
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          name: Release ${{ github.ref_name }}
          body: |
            ## 🐺 Kito ${{ steps.version.outputs.VERSION }}
            
            ### Installation
            ```bash
            npm install kitojs@${{ steps.version.outputs.VERSION }}
            # or
            pnpm add kitojs@${{ steps.version.outputs.VERSION }}
            ```
            
            ### What's Changed
            See the changelog for details.
            
            ### Documentation
            Visit kito.pages.dev for full documentation.
          draft: false
          prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .gitignore
================================================
# typescript
node_modules

# rust
/target

================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "3"
members = ["packages/core", "cli"]

[profile.release]
lto = "fat"
codegen-units = 1
panic = "abort"
opt-level = 3
strip = true


================================================
FILE: bench/cases/basic/elysia.ts
================================================
import { Elysia } from "elysia";
import { node } from "@elysiajs/node";

declare const Bun: any;

export function start(port: number): { stop: () => void } {
  const isBun = typeof Bun !== "undefined";

  const app = isBun ? new Elysia() : new Elysia({ adapter: node() });

  app.get("/", () => "hello world!");

  const server = app.listen(port);

  return {
    stop: async () => server.stop(),
  };
}


================================================
FILE: bench/cases/basic/express.ts
================================================
import express from "express";

export function start(port: number): { stop: () => void } {
  const app = express();

  app.get("/", (req, res) => {
    res.send("hello world!");
  });

  const appListen = app.listen(port);

  return {
    stop: async () => appListen.close(),
  };
}


================================================
FILE: bench/cases/basic/fastify.ts
================================================
import Fastify from "fastify";

export function start(port: number): { stop: () => void } {
  const app = Fastify({
    logger: false,
  });

  app.get("/", (request, reply) => {
    reply.send("hello world!");
  });

  app.listen({ port });

  return {
    stop: async () => await app.close(),
  };
}


================================================
FILE: bench/cases/basic/hapi.ts
================================================
import Hapi from "@hapi/hapi";

export function start(port: number): { stop: () => void } {
  const app = Hapi.server({ port });

  app.route({
    method: "GET",
    path: "/",
    handler: (request, h) => {
      return "hello world!";
    },
  });

  (async () => await app.start())();

  return {
    stop: async () => await app.stop(),
  };
}


================================================
FILE: bench/cases/basic/hono.ts
================================================
import { serve } from "@hono/node-server";
import { Hono } from "hono";

declare const Bun: any;

export function start(port: number): { stop: () => void } {
  const app = new Hono();

  app.get("/", (c) => c.text("hello world!"));

  if (typeof Bun !== "undefined") {
    const server = Bun.serve({
      fetch: app.fetch,
      port,
    });

    return {
      stop: () => server.stop(),
    };
  }

  const server = serve({
    fetch: app.fetch,
    port,
  });

  return {
    stop: async () => server.close(),
  };
}


================================================
FILE: bench/cases/basic/kito.ts
================================================
import { server } from "kitojs";

export function start(port: number): { stop: () => void } {
  const app = server();

  app.get("/", (ctx) => {
    ctx.res.send("hello world!");
  });

  app.listen(port);

  return {
    stop: async () => app.close(),
  };
}


================================================
FILE: bench/cases/basic/koa.ts
================================================
import Koa from "koa";
import Router from "@koa/router";

export function start(port: number): { stop: () => void } {
  const app = new Koa();
  const router = new Router();

  router.get("/", (ctx) => {
    ctx.body = "hello world!";
  });

  app.use(router.routes());
  app.use(router.allowedMethods());

  const appListen = app.listen(port);

  return {
    stop: async () => appListen.close(),
  };
}


================================================
FILE: bench/cases/basic/restify.ts
================================================
import restify from "restify";

export function start(port: number): { stop: () => void } {
  const app = restify.createServer();

  app.get("/", (req, res, next) => {
    res.send("hello world!");
    return next();
  });

  app.listen(port);

  return {
    stop: async () => app.close(),
  };
}


================================================
FILE: bench/cases/basic/tinyhttp.ts
================================================
import { App } from "@tinyhttp/app";

export function start(port: number): { stop: () => void } {
  const app = new App();

  app.get("/", (req, res) => {
    res.send("hello world!");
  });

  const appListen = app.listen(port);

  return {
    stop: async () => appListen.close(),
  };
}


================================================
FILE: bench/config.ts
================================================
type FrameworkConfig = string;

type FrameworkRuntime = "bun" | "node";

export default {
  frameworks: [
    "kito",
    "elysia",
    "express",
    "fastify",
    "hono",
    "restify",
    "tinyhttp",
    "koa",
    "hapi",
  ] satisfies FrameworkConfig[],
  hostname: "localhost",

  connections: 100,
  pipelining: 10,
  duration: 30,
  workers: undefined,

  chart: {
    enabled: true,
    output: "results/charts/result.png",
  },
};

export type { FrameworkConfig, FrameworkRuntime };


================================================
FILE: bench/package.json
================================================
{
  "name": "@kitojs/bench",
  "description": "Kito's benchmarks.",
  "private": true,
  "type": "module",
  "scripts": {
    "bench:run": "bun run runBench.ts",
    "bench:node": "bun run runBench.ts --exclude-runtime=bun",
    "bench:bun": "bun run runBench.ts --exclude-runtime=node"
  },
  "dependencies": {
    "@elysiajs/node": "^1.4.2",
    "@hapi/hapi": "^21.4.3",
    "@hono/node-server": "^1.19.6",
    "@koa/router": "^14.0.0",
    "@tinyhttp/app": "^3.0.1",
    "chart.js": "^4.5.1",
    "elysia": "^1.4.16",
    "express": "^5.1.0",
    "fastify": "^5.6.1",
    "hono": "^4.10.4",
    "kitojs": "workspace:*",
    "koa": "^3.1.1",
    "restify": "^11.1.0",
    "skia-canvas": "^3.0.8"
  },
  "devDependencies": {
    "@types/autocannon": "^7.12.7",
    "@types/express": "^5.0.5",
    "@types/koa": "^3.0.1",
    "@types/koa__router": "^12.0.5",
    "@types/restify": "^8.5.12",
    "tsx": "^4.20.6",
    "typescript": "^5.9.2"
  }
}


================================================
FILE: bench/readme.md
================================================
<img src="https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-logo.svg" width="200px" align="right" />

# Kito - `benchmarks`

Performance benchmarks comparing Kito against popular Node.js web frameworks.

---

## 📊 Latest Results

![Benchmark Results](results/charts/result-node.png)

> **Note:** Benchmarks are automatically updated on each release.

---

## 🎯 Benchmarked Frameworks

- **Kito** - High-performance TypeScript framework written in Rust
- **Fastify** - Fast and low overhead web framework
- **Hono** - Fast web framework for the edge
- **Express** - Fast, unopinionated web framework
- **Koa** - Expressive middleware framework
- **Restify** - REST API framework
- **TinyHTTP** - Lightweight Express-like framework
- **Hapi** - Rich framework for building applications

---

## 🔧 Benchmark Configuration

```typescript
{
  connections: 100,
  pipelining: 10,
  duration: 30, // seconds
  workers: undefined // auto
}
```

All frameworks are tested with a simple "Hello World" endpoint to measure raw performance.

---

## 🚀 Running Benchmarks

### Prerequisites

```bash
pnpm install
```

### Run All Benchmarks

```bash
pnpm bench:run basic
```

This will:
1. Start each framework on sequential ports (3000, 3001, ...)
2. Run [wrk](https://github.com/wg/wrk) load tests
3. Generate comparison charts
4. Save detailed results to `results/data/`

### Mixing Node and Bun runtimes

Some framework adapters only work on Node.js while others can run under Bun. You can pin the runtime per framework in `config.ts`:

```ts
frameworks: [
  { name: "kito", runtime: "bun" },
  { name: "elysia", runtime: "bun" },
  { name: "restify", runtime: "node" },
  "koa", // uses whichever runtime you launch the runner with
];
```

- Default (string) entries execute inside the same runtime that starts `runBench.ts`.
- `runtime: "bun"` executes via `pnpm dlx bun run ...`, so make sure `pnpm` is available (it will download Bun on demand).
- `runtime: "node"` executes via `pnpm dlx tsx ...`, so no local CLI install is required beyond `pnpm`.

---

## 📁 Project Structure

```
bench/
├── cases/
│   └── basic/           # Basic "Hello World" benchmarks
│       ├── kito.ts
│       ├── fastify.ts
│       ├── express.ts
│       └── ...
├── results/
│   ├── charts/          # Generated benchmark charts
│   └── data/            # Raw JSON results
├── utils/
│   ├── http.ts          # Wrk runner
│   └── chart.ts         # Chart generation
├── config.ts            # Benchmark configuration
└── runBench.ts          # Main benchmark runner
```

---

## 📈 Metrics Measured

- **Requests/sec** - Average requests per second
- **Latency (ms)** - Average response time in milliseconds
- **Throughput (bytes/sec)** - Average data throughput

---

## 🎨 Adding New Benchmarks

1. Create a new folder in `cases/` (e.g., `cases/routing/`)
2. Add framework implementations following the pattern:

```typescript
export function start(port: number): { stop: () => void } {
  const app = createServer();
  
  app.get("/", handler);
  app.listen(port);
  
  return {
    stop: async () => app.close(),
  };
}
```

3. Run your benchmark:

```bash
pnpm bench:run routing
```

---

## 📊 Understanding Results

### Requests/sec (Higher is better)
Number of requests the server can handle per second.

### Latency (Lower is better)
Time taken to receive a response. Includes network and processing time.

### Throughput (Higher is better)
Amount of data transferred per second.

---

## ⚙️ Configuration

Edit `config.ts` to customize:

```typescript
export default {
  frameworks: ["kito", "fastify", "hono", ...],
  connections: 100,      // Concurrent connections
  pipelining: 10,        // Requests per connection
  duration: 30,          // Test duration in seconds
  chart: {
    enabled: true,
    output: "results/charts/result.png"
  }
};
```

---

## 🔬 Methodology

- All tests run on the same machine with identical conditions
- Each framework uses its recommended setup and defaults
- Tests measure only the framework overhead, not business logic
- Results are averaged over the test duration

---

## 📝 Notes

- Benchmarks are indicative and may vary based on hardware
- Real-world performance depends on application complexity
- These tests measure raw throughput, not production scenarios
- All frameworks are excellent choices for different use cases

---

## 🤝 Contributing

Found an issue with the benchmarks? Want to add a new framework?

1. Fork the repository
2. Add your changes
3. Run the benchmarks locally
4. Submit a pull request

---

## 📄 License

Licensed under the [MIT License](../license).

---

[![blazingly fast](https://blazingly.fast/api/badge.svg?repo=kitojs%2Fkito)](https://blazingly.fast)


================================================
FILE: bench/results/comparison-bun.json
================================================
{
  "winner": "kito",
  "runtime": "bun",
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "ranking": [
    {
      "rank": 1,
      "framework": "kito",
      "requests": 283106.67,
      "latency": 0.39031,
      "throughput": 32275169.28,
      "difference": "0%"
    },
    {
      "rank": 2,
      "framework": "elysia",
      "requests": 149351.06,
      "latency": 0.6690900000000001,
      "throughput": 19115540.48,
      "difference": "-47.25%"
    },
    {
      "rank": 3,
      "framework": "hono",
      "requests": 104550.49,
      "latency": 0.96,
      "throughput": 13379829.76,
      "difference": "-63.07%"
    },
    {
      "rank": 4,
      "framework": "fastify",
      "requests": 58216.12,
      "latency": 1.72,
      "throughput": 7507804.16,
      "difference": "-79.44%"
    },
    {
      "rank": 5,
      "framework": "tinyhttp",
      "requests": 40612.94,
      "latency": 2.46,
      "throughput": 7843348.48,
      "difference": "-85.65%"
    },
    {
      "rank": 6,
      "framework": "express",
      "requests": 36992.17,
      "latency": 2.7,
      "throughput": 7098859.52,
      "difference": "-86.93%"
    },
    {
      "rank": 7,
      "framework": "koa",
      "requests": 32931.2,
      "latency": 3.03,
      "throughput": 4246732.8,
      "difference": "-88.37%"
    },
    {
      "rank": 8,
      "framework": "hapi",
      "requests": 25239.19,
      "latency": 3.96,
      "throughput": 4414504.96,
      "difference": "-91.08%"
    }
  ]
}


================================================
FILE: bench/results/comparison-node.json
================================================
{
  "winner": "kito",
  "runtime": "node",
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "ranking": [
    {
      "rank": 1,
      "framework": "kito",
      "requests": 282020.9,
      "latency": 0.38923,
      "throughput": 32149340.16,
      "difference": "0%"
    },
    {
      "rank": 2,
      "framework": "fastify",
      "requests": 42597.14,
      "latency": 2.7,
      "throughput": 7539261.44,
      "difference": "-84.90%"
    },
    {
      "rank": 3,
      "framework": "hono",
      "requests": 37869.16,
      "latency": 3.2,
      "throughput": 6668943.36,
      "difference": "-86.57%"
    },
    {
      "rank": 4,
      "framework": "koa",
      "requests": 28399.52,
      "latency": 4.14,
      "throughput": 5001707.52,
      "difference": "-89.93%"
    },
    {
      "rank": 5,
      "framework": "restify",
      "requests": 26687.06,
      "latency": 4.31,
      "throughput": 4959764.48,
      "difference": "-90.54%"
    },
    {
      "rank": 6,
      "framework": "hapi",
      "requests": 26628.01,
      "latency": 4.48,
      "throughput": 5913968.64,
      "difference": "-90.56%"
    },
    {
      "rank": 7,
      "framework": "tinyhttp",
      "requests": 24126.25,
      "latency": 4.89,
      "throughput": 5788139.52,
      "difference": "-91.45%"
    },
    {
      "rank": 8,
      "framework": "elysia",
      "requests": 15821.79,
      "latency": 7.81,
      "throughput": 2548039.68,
      "difference": "-94.39%"
    },
    {
      "rank": 9,
      "framework": "express",
      "requests": 9914.66,
      "latency": 12.59,
      "throughput": 2369781.76,
      "difference": "-96.48%"
    }
  ]
}


================================================
FILE: bench/results/data/bun/elysia.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "elysia",
  "results": {
    "requests": {
      "average": 149351.06
    },
    "latency": {
      "average": 0.6690900000000001
    },
    "throughput": {
      "average": 19115540.48
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/express.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "express",
  "results": {
    "requests": {
      "average": 36992.17
    },
    "latency": {
      "average": 2.7
    },
    "throughput": {
      "average": 7098859.52
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/fastify.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "fastify",
  "results": {
    "requests": {
      "average": 58216.12
    },
    "latency": {
      "average": 1.72
    },
    "throughput": {
      "average": 7507804.16
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/hapi.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "hapi",
  "results": {
    "requests": {
      "average": 25239.19
    },
    "latency": {
      "average": 3.96
    },
    "throughput": {
      "average": 4414504.96
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/hono.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "hono",
  "results": {
    "requests": {
      "average": 104550.49
    },
    "latency": {
      "average": 0.96
    },
    "throughput": {
      "average": 13379829.76
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/kito.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "kito",
  "results": {
    "requests": {
      "average": 283106.67
    },
    "latency": {
      "average": 0.39031
    },
    "throughput": {
      "average": 32275169.28
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/koa.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "koa",
  "results": {
    "requests": {
      "average": 32931.2
    },
    "latency": {
      "average": 3.03
    },
    "throughput": {
      "average": 4246732.8
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/bun/tinyhttp.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "bun",
  "framework": "tinyhttp",
  "results": {
    "requests": {
      "average": 40612.94
    },
    "latency": {
      "average": 2.46
    },
    "throughput": {
      "average": 7843348.48
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/elysia.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "elysia",
  "results": {
    "requests": {
      "average": 15821.79
    },
    "latency": {
      "average": 7.81
    },
    "throughput": {
      "average": 2548039.68
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/express.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "express",
  "results": {
    "requests": {
      "average": 9914.66
    },
    "latency": {
      "average": 12.59
    },
    "throughput": {
      "average": 2369781.76
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/fastify.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "fastify",
  "results": {
    "requests": {
      "average": 42597.14
    },
    "latency": {
      "average": 2.7
    },
    "throughput": {
      "average": 7539261.44
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/hapi.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "hapi",
  "results": {
    "requests": {
      "average": 26628.01
    },
    "latency": {
      "average": 4.48
    },
    "throughput": {
      "average": 5913968.64
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/hono.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "hono",
  "results": {
    "requests": {
      "average": 37869.16
    },
    "latency": {
      "average": 3.2
    },
    "throughput": {
      "average": 6668943.36
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/kito.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "kito",
  "results": {
    "requests": {
      "average": 282020.9
    },
    "latency": {
      "average": 0.38923
    },
    "throughput": {
      "average": 32149340.16
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/koa.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "koa",
  "results": {
    "requests": {
      "average": 28399.52
    },
    "latency": {
      "average": 4.14
    },
    "throughput": {
      "average": 5001707.52
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/restify.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "restify",
  "results": {
    "requests": {
      "average": 26687.06
    },
    "latency": {
      "average": 4.31
    },
    "throughput": {
      "average": 4959764.48
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/results/data/node/tinyhttp.json
================================================
{
  "machine": {
    "cpu": "Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz",
    "memory": "31 GB",
    "platform": "linux 6.12.48-1-MANJARO"
  },
  "runtime": "node",
  "framework": "tinyhttp",
  "results": {
    "requests": {
      "average": 24126.25
    },
    "latency": {
      "average": 4.89
    },
    "throughput": {
      "average": 5788139.52
    }
  },
  "previousResults": null,
  "comparison": null
}


================================================
FILE: bench/runBench.ts
================================================
import { runBenchmark } from "./utils/http.ts";

import config, { type FrameworkRuntime } from "./config.ts";
const { hostname, frameworks, chart } = config;

import { generateChart } from "./utils/chart.ts";
import { waitForServerReady } from "./utils/wait.ts";

import fs from "node:fs";
import { spawn, type ChildProcess } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";
import os from "node:os";

type BenchmarkResult = {
  framework: string;
  result: {
    requests: { average: number };
    latency: { average: number };
    throughput: { average: number };
  };
};

type RunningBenchmark = {
  stop: () => Promise<void> | void;
};

type NormalizedFramework = {
  name: string;
  runtime: FrameworkRuntime;
};

const CURRENT_RUNTIME: FrameworkRuntime =
  typeof (globalThis as { Bun?: unknown }).Bun !== "undefined" ? "bun" : "node";

const PROJECT_ROOT = path.dirname(fileURLToPath(import.meta.url));
const RUNNER_ENTRY = path.join(PROJECT_ROOT, "utils", "frameworkRunner.ts");
const PNPM_BIN = process.platform === "win32" ? "pnpm.cmd" : "pnpm";

async function launchFramework(
  benchName: string,
  framework: NormalizedFramework,
  port: number,
): Promise<RunningBenchmark> {
  if (framework.runtime === CURRENT_RUNTIME) {
    const mod = await import(`./cases/${benchName}/${framework.name}.ts`);
    const bench = mod.default || mod;
    const instance: RunningBenchmark = bench.start(port);

    return {
      stop: async () => {
        if (typeof instance?.stop === "function") {
          await instance.stop();
        }
      },
    };
  }

  const child = spawnFrameworkProcess(
    framework.runtime,
    benchName,
    framework.name,
    port,
  );

  return {
    stop: async () => await stopChildProcess(child),
  };
}

function spawnFrameworkProcess(
  targetRuntime: FrameworkRuntime,
  benchName: string,
  frameworkName: string,
  port: number,
): ChildProcess {
  if (targetRuntime === "node") {
    return spawn(
      PNPM_BIN,
      ["dlx", "tsx", RUNNER_ENTRY, benchName, frameworkName, String(port)],
      {
        stdio: "inherit",
        cwd: PROJECT_ROOT,
      },
    );
  }

  return spawn(
    PNPM_BIN,
    ["dlx", "bun", "run", RUNNER_ENTRY, benchName, frameworkName, String(port)],
    {
      stdio: "inherit",
      cwd: PROJECT_ROOT,
    },
  );
}

async function stopChildProcess(child: ChildProcess): Promise<void> {
  if (!child.killed) {
    child.kill("SIGTERM");
  }

  await new Promise<void>((resolve, reject) => {
    child.once("error", reject);
    child.once("exit", (code, signal) => {
      if (code === 0 || signal === "SIGTERM") {
        resolve();
      } else {
        reject(
          new Error(`Framework runner exited with code ${code ?? "null"}`),
        );
      }
    });
  });
}

function getMachineSpecs() {
  const cpu = os.cpus()[0].model;
  const memory = `${Math.round(os.totalmem() / 1024 / 1024 / 1024)} GB`;
  const platform = `${os.platform()} ${os.release()}`;

  return { cpu, memory, platform };
}

async function main() {
  const benchName = process.argv[2];
  if (!benchName) {
    console.error(
      "You must pass the name of the benchmark, e.g.: pnpm bench:run basic",
    );
    process.exit(1);
  }

  const args = process.argv.slice(3);
  const excludeRuntimes =
    args
      .find((arg) => arg.startsWith("--exclude-runtime="))
      ?.split("=")[1]
      ?.split(",") || [];

  const excludeFrameworks =
    args
      .find((arg) => arg.startsWith("--exclude-framework="))
      ?.split("=")[1]
      ?.split(",") || [];

  const runtimes: FrameworkRuntime[] = ["node", "bun"].filter(
    (r) => !excludeRuntimes.includes(r),
  ) as FrameworkRuntime[];

  const machine = getMachineSpecs();

  for (const runtime of runtimes) {
    console.log(`\n${"-".repeat(40)}`);
    console.log(`Running benchmarks on ${runtime.toUpperCase()} runtime`);
    console.log(`${"-".repeat(40)}\n`);

    const results: BenchmarkResult[] = [];
    let port = 3000;

    for (const frameworkName of frameworks) {
      if (excludeFrameworks.includes(frameworkName)) {
        console.log(`Skipping ${frameworkName} (excluded via flag)`);
        continue;
      }

      if (runtime === "bun" && frameworkName === "restify") {
        console.log(
          `Skipping ${frameworkName} (not compatible with Bun runtime)`,
        );

        continue;
      }

      const framework: NormalizedFramework = {
        name: frameworkName,
        runtime: runtime,
      };

      const benchInstance = await launchFramework(benchName, framework, port);
      await waitForServerReady(port);

      console.log(
        `Running benchmark for ${framework.name} (runtime: ${framework.runtime})...`,
      );
      const URL = `http://${hostname}:${port}`;

      const result = await runBenchmark(URL);
      results.push({ framework: framework.name, result });

      port++;

      await benchInstance.stop();
    }

    console.table(
      results.map(({ framework, result }) => ({
        Framework: framework,
        "Requests/sec": result.requests.average,
        "Latency (ms)": result.latency.average,
        "Throughput (bytes/sec)": result.throughput.average,
      })),
    );

    if (chart?.enabled) {
      const output =
        chart.output?.replace("result.png", `result-${runtime}.png`) ||
        `results/charts/result-${runtime}.png`;
      await generateChart(
        {
          frameworks: results.map((r) => r.framework),
          requests: results.map((r) => r.result.requests.average),
          latency: results.map((r) => r.result.latency.average),
          throughput: results.map((r) => r.result.throughput.average),
        },
        output,
        runtime,
      );
    }

    for (const result of results) {
      const OUTPUT_PATH = `results/data/${runtime}`;
      const FILE_PATH = `${OUTPUT_PATH}/${result.framework}.json`;

      let previousResults = null;
      let comparison = null;

      if (fs.existsSync(FILE_PATH)) {
        try {
          const content = JSON.parse(fs.readFileSync(FILE_PATH, "utf-8"));
          if (content.results) {
            previousResults = content.results;

            const calcDiff = (current: number, previous: number) => {
              const diff = ((current - previous) / previous) * 100;
              return `${diff > 0 ? "+" : ""}${diff.toFixed(2)}%`;
            };

            comparison = {
              requests: calcDiff(
                result.result.requests.average,
                previousResults.requests.average,
              ),
              latency: calcDiff(
                result.result.latency.average,
                previousResults.latency.average,
              ),
              throughput: calcDiff(
                result.result.throughput.average,
                previousResults.throughput.average,
              ),
            };
          }
        } catch (_) {}
      }

      const outputData = {
        machine,
        runtime,
        framework: result.framework,
        results: result.result,
        previousResults,
        comparison,
      };

      const data = JSON.stringify(outputData, null, "\t");

      if (!fs.existsSync(OUTPUT_PATH)) {
        fs.mkdirSync(OUTPUT_PATH, { recursive: true });
      }

      fs.writeFileSync(FILE_PATH, data);
    }

    const sortedResults = [...results].sort(
      (a, b) => b.result.requests.average - a.result.requests.average,
    );

    const winner = sortedResults[0];

    const ranking = sortedResults.map((item, index) => {
      const diff =
        ((item.result.requests.average - winner.result.requests.average) /
          winner.result.requests.average) *
        100;

      return {
        rank: index + 1,
        framework: item.framework,
        requests: item.result.requests.average,
        latency: item.result.latency.average,
        throughput: item.result.throughput.average,
        difference: index === 0 ? "0%" : `${diff.toFixed(2)}%`,
      };
    });

    const leaderboard = {
      winner: winner.framework,
      runtime,
      machine,
      ranking,
    };

    fs.writeFileSync(
      `results/comparison-${runtime}.json`,
      JSON.stringify(leaderboard, null, "\t"),
    );
  }

  console.log(`\n${"-".repeat(40)}`);
  console.log("✅ All benchmarks completed!");
  console.log(`${"-".repeat(40)}\n`);

  process.exit(0);
}

(async () => await main())();


================================================
FILE: bench/tsconfig.json
================================================
{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    "noEmit": true,
    "allowImportingTsExtensions": true
  },
  "references": [{ "path": "../packages/kitojs" }]
}


================================================
FILE: bench/utils/chart.ts
================================================
import {
  BarController,
  BarElement,
  CategoryScale,
  Chart,
  LinearScale,
  Title,
  Tooltip,
  Legend,
} from "chart.js";
import { Canvas } from "skia-canvas";
import fs from "node:fs/promises";

Chart.register([
  BarController,
  BarElement,
  CategoryScale,
  LinearScale,
  Title,
  Tooltip,
  Legend,
]);

type ChartData = {
  frameworks: string[];
  requests: number[];
  latency: number[];
  throughput: number[];
};

export async function generateChart(
  data: ChartData,
  outputPath: string,
  runtime?: string,
) {
  try {
    const canvas = new Canvas(1000, 600);

    const colors = [
      "#3b82f6", // blue
      "#10b981", // green
      "#f59e0b", // amber
      "#8b5cf6", // purple
      "#ec4899", // pink
      "#06b6d4", // cyan
    ];

    const chart = new Chart(canvas as any, {
      type: "bar",
      data: {
        labels: data.frameworks.map(
          (f) => f.charAt(0).toUpperCase() + f.slice(1),
        ),
        datasets: [
          {
            label: "Requests/sec",
            data: data.requests,
            backgroundColor: "#3b82f6",
            borderRadius: 8,
            borderSkipped: false,
          },
          {
            label: "Latency (ms)",
            data: data.latency,
            backgroundColor: "#10b981",
            borderRadius: 8,
            borderSkipped: false,
            yAxisID: "y1",
          },
        ],
      },
      options: {
        responsive: false,
        layout: {
          padding: {
            top: 20,
            bottom: 20,
            left: 20,
            right: 20,
          },
        },
        plugins: {
          legend: {
            display: true,
            position: "top",
            align: "end",
            labels: {
              color: "#1f2937",
              font: {
                size: 14,
                weight: 600,
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
              padding: 15,
              usePointStyle: true,
              pointStyle: "rectRounded",
            },
          },
          title: {
            display: true,
            text: runtime
              ? `Benchmark Results - ${runtime.toUpperCase()}`
              : "Benchmark Results",
            color: "#1f2937",
            font: {
              size: 28,
              weight: "bold",
              family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
            },
            padding: {
              top: 10,
              bottom: 30,
            },
          },
          tooltip: {
            backgroundColor: "rgba(0, 0, 0, 0.8)",
            titleFont: {
              size: 14,
              weight: "bold",
              family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
            },
            bodyFont: {
              size: 13,
              family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
            },
            padding: 12,
            cornerRadius: 8,
            displayColors: false,
            callbacks: {
              label: (context) => {
                const label = context.dataset.label || "";
                const value = context.parsed.y;

                if (label.includes("Latency")) {
                  return `${label}: ${value?.toFixed(2)} ms`;
                }

                return `${label}: ${value?.toLocaleString()} req/s`;
              },
            },
          },
        },
        scales: {
          x: {
            grid: {
              display: false,
            },
            ticks: {
              color: "#4b5563",
              font: {
                size: 16,
                weight: 600,
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
              padding: 10,
            },
            border: {
              display: false,
            },
          },
          y: {
            beginAtZero: true,
            position: "left",
            grid: {
              color: "#e5e7eb",
              lineWidth: 1,
            },
            ticks: {
              color: "#3b82f6",
              font: {
                size: 13,
                weight: 600,
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
              padding: 10,
              callback: (value) => {
                return value.toLocaleString();
              },
            },
            border: {
              display: false,
            },
            title: {
              display: true,
              text: "Requests/sec",
              color: "#3b82f6",
              font: {
                size: 13,
                weight: "bold",
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
            },
          },
          y1: {
            beginAtZero: true,
            position: "right",
            grid: {
              display: false,
            },
            ticks: {
              color: "#10b981",
              font: {
                size: 13,
                weight: 600,
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
              padding: 10,
              callback: (value) => {
                let valueNumber = value as number;
                return valueNumber.toFixed(1);
              },
            },
            border: {
              display: false,
            },
            title: {
              display: true,
              text: "Latency (ms)",
              color: "#10b981",
              font: {
                size: 13,
                weight: "bold",
                family: "'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif",
              },
            },
          },
        },
      },
    });

    const dir = outputPath.substring(0, outputPath.lastIndexOf("/"));
    if (dir) {
      await fs.mkdir(dir, { recursive: true });
    }

    const pngBuffer = await canvas.toBuffer("png", {
      matte: "white",
      density: 2,
    });

    await fs.writeFile(outputPath, pngBuffer);

    console.log(`✅ Chart saved to ${outputPath}`);

    chart.destroy();
  } catch (err) {
    console.error("Error generating chart:", err);
  }
}


================================================
FILE: bench/utils/frameworkRunner.ts
================================================
const [, , benchName, frameworkName, portArg] = process.argv;

if (!benchName || !frameworkName || !portArg) {
  console.error(
    "Missing arguments. Usage: frameworkRunner <bench> <framework> <port>",
  );
  process.exit(1);
}

const port = Number(portArg);
if (!Number.isFinite(port)) {
  console.error(`Invalid port provided to frameworkRunner: ${portArg}`);
  process.exit(1);
}

const mod = await import(`../cases/${benchName}/${frameworkName}.ts`);
const bench = mod.default || mod;
const instance = bench.start(port);

async function shutdown(code = 0) {
  try {
    if (typeof instance?.stop === "function") {
      await instance.stop();
    }
  } catch (error) {
    console.error("Failed to stop framework cleanly", error);
  } finally {
    process.exit(code);
  }
}

process.on("SIGTERM", () => void shutdown());
process.on("SIGINT", () => void shutdown());
process.on("uncaughtException", async (error) => {
  console.error(error);
  await shutdown(1);
});

export {};


================================================
FILE: bench/utils/http.ts
================================================
import { exec } from "node:child_process";
import config from "../config.ts";

const { duration, connections } = config;

export type WrkResult = {
  requests: { average: number };
  latency: { average: number };
  throughput: { average: number };
};

export const runBenchmark = (url: string) => {
  return new Promise<WrkResult>((resolve, reject) => {
    const cmd = `wrk -t${connections} -c${connections} -d${duration}s -H "Connection: keep-alive" ${url}`;

    exec(cmd, (err, stdout) => {
      if (err) {
        reject(err);
        return;
      }

      const output = stdout.toString();

      const reqMatch = output.match(/Requests\/sec:\s*([\d.]+)/);
      const requests = reqMatch ? parseFloat(reqMatch[1]) : 0;

      const latMatch = output.match(/Latency\s+([\d.]+)(ms|s|us)/);
      let latency = 0;
      if (latMatch) {
        const v = parseFloat(latMatch[1]);
        const unit = latMatch[2];
        if (unit === "s") latency = v * 1000;
        else if (unit === "us") latency = v / 1000;
        else latency = v;
      }

      const tpMatch = output.match(/Transfer\/sec:\s*([\d.]+)(KB|MB|B)/);
      let throughput = 0;
      if (tpMatch) {
        const v = parseFloat(tpMatch[1]);
        const unit = tpMatch[2];
        if (unit === "MB") throughput = v * 1024 * 1024;
        else if (unit === "KB") throughput = v * 1024;
        else throughput = v;
      }

      resolve({
        requests: { average: requests },
        latency: { average: latency },
        throughput: { average: throughput },
      });
    });
  });
};


================================================
FILE: bench/utils/wait.ts
================================================
import net from "node:net";

export function waitForServerReady(port: number, retries = 50): Promise<void> {
  return new Promise((resolve, reject) => {
    (function check(retries: number) {
      const socket = net.createConnection(port, "localhost");

      socket.on("connect", () => {
        socket.end();
        resolve();
      });

      socket.on("error", () => {
        if (retries <= 0) return reject(new Error("Server not ready"));
        setTimeout(() => check(--retries), 50);
      });
    })(retries);
  });
}


================================================
FILE: biome.json
================================================
{
  "$schema": "https://biomejs.dev/schemas/2.2.3/schema.json",
  "vcs": {
    "enabled": false,
    "clientKind": "git",
    "useIgnoreFile": false
  },
  "files": {
    "ignoreUnknown": false,
    "includes": ["**", "packages/**", "examples/**", "bench/**"]
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space"
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double"
    }
  },
  "assist": {
    "enabled": true,
    "actions": {
      "source": {
        "organizeImports": "on"
      }
    }
  }
}


================================================
FILE: cli/.gitignore
================================================
bin/
dist/

================================================
FILE: cli/Cargo.toml
================================================
[package]
name = "kito"                                  # cli
version = "0.1.0"
edition = "2024"
authors = ["Nehuén <github.com/nehu3n>"]
description = "🐺 Kito's official CLI."
license = "MIT"
repository = "https://github.com/kitojs/kito"
readme = "readme.md"
include = ["src/*", "Cargo.toml", "readme.md"]

[[bin]]
name = "kito"
path = "src/main.rs"

[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = true

[dependencies]
async-trait = "0.1.89"
clap = { version = "4.5.47", features = ["derive"] }
paste = "1.0.15"
tokio = { version = "1.47.1", features = ["full"] }


================================================
FILE: cli/install.js
================================================


================================================
FILE: cli/package.json
================================================
{
  "name": "@kitojs/cli",
  "version": "1.0.0",
  "description": "🍄 Kito's official CLI.",
  "bin": {
    "kito": "bin/kito"
  },

  "scripts": {
    "postinstall": "node install.js"
  },

  "keywords": [],

  "homepage": "https://github.com/kitojs/kito",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kitojs/kito.git"
  },
  "bugs": {
    "url": "https://github.com/kitojs/kito/issues"
  },

  "license": "MIT",
  "author": "Nehuén <github.com/nehu3n>",

  "main": "bin/kito",

  "os": [
    "darwin",
    "linux",
    "win32"
  ],
  "cpu": [
    "x64",
    "arm64"
  ],

  "files": [
    "bin/",
    "install.js",
    "readme.md"
  ]
}


================================================
FILE: cli/src/commands.rs
================================================
use crate::register_commands;

use async_trait::async_trait;

#[async_trait]
pub(crate) trait Command {
    async fn run(&self) -> Result<(), ()>;
}

register_commands!();


================================================
FILE: cli/src/main.rs
================================================
mod commands;
mod utils;

use async_trait::async_trait;
use clap::{Parser, Subcommand};

use crate::commands::Command;

#[derive(Parser)]
#[command(
    name = "kito",
    version = env!("CARGO_PKG_VERSION"),
    about = env!("CARGO_PKG_DESCRIPTION")
)]
#[command(arg_required_else_help = true)]
struct Cli {
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {}

#[async_trait]
impl Command for Commands {
    async fn run(&self) -> Result<(), ()> {
        // match self {}

        Ok(())
    }
}

#[tokio::main]
async fn main() {
    let cli = Cli::parse();

    if let Some(cmd) = cli.command {
        let cmd_run = cmd.run().await;
        if cmd_run.is_err() {
            std::process::exit(1);
        }
    }
}


================================================
FILE: cli/src/utils.rs
================================================
#[macro_export]
macro_rules! register_commands {
    ($($name:ident),*) => {
        $(
            pub(crate) mod $name;
            paste::paste! {
                pub(crate) use $name::[<$name:camel Command>];
            }
        )*
    }
}


================================================
FILE: cliff.toml
================================================
[changelog]
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}{% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}
{% endfor %}
{% endfor %}
"""
trim = true
render_always = true
postprocessors = [
    { pattern = '<REPO>', replace = "https://github.com/kitojs/kito" },
]

[git]
conventional_commits = true
filter_unconventional = true
require_conventional = false
split_commits = false
commit_preprocessors = [
    { pattern = '\\((\\w+\\s)?#([0-9]+)\\)', replace = "([#${2}](<REPO>/issues/${2}))" },
    { pattern = '.*', replace_command = 'typos --write-changes -' },
]
protect_breaking_commits = false

commit_parsers = [
    { message = "^feat", group = "<!-- 0 -->🚀 Features" },
    { message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
    { message = "^perf", group = "<!-- 4 -->⚡ Performance" },
    { message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
    { message = "^style", group = "<!-- 5 -->🎨 Styling" },
    { message = "^test", group = "<!-- 6 -->🧪 Testing" },
    { message = "^doc", group = "<!-- 3 -->📚 Documentation" },
    { message = "^chore\\(release\\): prepare for", skip = true },
    { message = "^chore\\(deps.*\\)", skip = true },
    { message = "^chore\\(pr\\)", skip = true },
    { message = "^chore\\(pull\\)", skip = true },
    { message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
    { body = ".*security", group = "<!-- 8 -->🛡️ Security" },
    { message = "^revert", group = "<!-- 9 -->◀️ Revert" },
    { message = ".*", group = "<!-- 10 -->💼 Other" },
]

filter_commits = false
link_parsers = []

use_branch_tags = false
topo_order = false
topo_order_commits = true
sort_commits = "oldest"
recurse_submodules = false

================================================
FILE: examples/fluent/basic.ts
================================================
import { server } from "kitojs";

server()
  .get("/", ({ res }) => res.send("hello world!"))
  .listen(3000);


================================================
FILE: examples/fluent/clustering/index.ts
================================================
import cluster from "node:cluster";
import { availableParallelism } from "node:os";

if (cluster.isPrimary) {
  const numCPUs = availableParallelism();

  console.log(`Primary ${process.pid} is running`);
  console.log(`Starting ${numCPUs} workers...`);

  for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
  import("./server");
}


================================================
FILE: examples/fluent/clustering/server.ts
================================================
import { server } from "kitojs";

server({
  reusePort: true, // this is required for clustering
})
  .get("/", ({ res }) => res.send("hello world!"))
  .listen(3000, () => {
    console.log(`Worker ${process.pid} listening on port 3000`);
  });


================================================
FILE: examples/fluent/extend.ts
================================================
import { server } from "kitojs";

interface Extends {
  user: { id: string; name: string };
}

server()
  .extend<Extends>((ctx) => {
    ctx.user = { id: "1", name: "Neo" };
  })
  .get("/", ({ res, user }) => {
    res.json({ user });
  })
  .listen(3000);


================================================
FILE: examples/fluent/file.ts
================================================
import { server } from "kitojs";

server()
  .get("/download", ({ res }) => {
    res.sendFile("public/banner.png", {
      root: "./",
      maxAge: 3600,
      lastModified: true,
      cacheControl: true,
      immutable: false,
    });
  })
  .get("/export", ({ res }) => {
    res.download("public/banner.png", "kito-banner.png");
  })
  .listen(3000);


================================================
FILE: examples/fluent/middlewares/index.ts
================================================
import { server } from "kitojs";

import { auth } from "./samples/auth";
import { logger } from "./samples/logger";

server()
  .use(logger)
  .get("/", auth, ({ res }) => res.send("hello world!"))
  .listen(3000);


================================================
FILE: examples/fluent/middlewares/samples/auth.ts
================================================
import { middleware } from "kitojs";

export const auth = middleware((ctx, next) => {
  const { req, res } = ctx;
  const header = req.headers.authorization;

  if (header && header === "Bearer secret_token") {
    return next();
  }

  res.status(401).send("unauthorized");
});


================================================
FILE: examples/fluent/middlewares/samples/logger.ts
================================================
import { middleware } from "kitojs";

export const logger = middleware((ctx, next) => {
  const { method, url } = ctx.req;
  const date = new Date().toISOString();

  console.log(`[${date}] ${method} ${url}`);
  return next();
});


================================================
FILE: examples/fluent/params.ts
================================================
import { server } from "kitojs";

server()
  .get("/:id", ({ req, res }) => res.send(req.params.id))
  .get("/multi/:id/:name", ({ req, res }) => {
    const { id, name } = req.params;
    res.json({ id, name });
  })
  .listen(3000);


================================================
FILE: examples/fluent/route.ts
================================================
import { server } from "kitojs";

server()
  .route("/")
  .get(({ res }) => {
    res.send("hello world!");
  })
  .post(({ req, res }) => {
    res.json({ body: req.body });
  })
  .end()
  .get("/bye", ({ res }) => {
    res.send("bye!");
  })
  .listen(3000);


================================================
FILE: examples/fluent/router/cats.ts
================================================
import { router } from "kitojs";

export default router()
  .get("/", ({ res }) => {
    res.send("hello cats!");
  })
  .post("/", ({ res }) => {
    res.json({ msg: "cat created!" });
  });


================================================
FILE: examples/fluent/router/index.ts
================================================
import { server } from "kitojs";
import cats from "./cats";

server()
  .mount("/cats", cats)
  .get("/", ({ res }) => res.send("hello world!"))
  .listen(3000);


================================================
FILE: examples/fluent/schemas/builder.ts
================================================
import { schema, server, t } from "kitojs";

const userSchema = schema({
  params: t.object({ id: t.str().uuid() }),
  query: t.object({ limit: t.num().max(100) }),
  body: t.object({ name: t.str().min(1) }),
});

server()
  .post(
    "/users:id",
    ({ req, res }) => {
      const { id } = req.params;
      const { limit } = req.query;
      const { name } = req.body;

      res.json({ id, limit, name });
    },
    userSchema,
  )
  .listen(3000);


================================================
FILE: examples/fluent/schemas/json.ts
================================================
import { schema, server } from "kitojs";

const userSchema = schema.json({
  params: {
    type: "object",
    properties: {
      id: { type: "string", format: "uuid" },
    },
    required: ["id"],
  },
  query: {
    type: "object",
    properties: {
      limit: { type: "number", maximum: 100 },
    },
    required: ["limit"],
  },
  body: {
    type: "object",
    properties: {
      name: { type: "string", minLength: 1 },
    },
    required: ["name"],
  },
});

server()
  .post(
    "/users/:id",
    ({ req, res }) => {
      // types are automatically inferred from userSchema
      const { id } = req.params;
      const { limit } = req.query;
      const { name } = req.body;

      res.json({ id, limit, name });
    },
    userSchema,
  )
  .listen(3000);


================================================
FILE: examples/fluent/streaming/sse.ts
================================================
import { server } from "kitojs";

server()
  .get("/", ({ res }) => {
    const sse = res.sse();

    sse.send("hello world!");

    sse.send(
      {
        msg: "this is a message",
      },
      "message",
    );

    sse.close();
  })
  .listen(3000);


================================================
FILE: examples/fluent/streaming/stream.ts
================================================
import { server } from "kitojs";

server()
  .get("/", ({ res }) => {
    const stream = res.stream();

    stream.write("Chunk 1\n");

    setTimeout(() => {
      stream.write("Chunk 2\n");
    }, 1000);

    setTimeout(() => {
      stream.end("Final chunk\n");
    }, 2000);
  })
  .listen(3000);


================================================
FILE: examples/fluent/unixSocket.ts
================================================
import { server } from "kitojs";

server()
  .get("/", ({ res }) => {
    res.send("Hello from Unix socket!");
  })
  .listen({ unixSocket: "./app.sock" });


================================================
FILE: examples/instance/basic.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/", ({ res }) => {
  res.send("hello world!");
});

app.listen(3000);


================================================
FILE: examples/instance/clustering/index.ts
================================================
import cluster from "node:cluster";
import { availableParallelism } from "node:os";

if (cluster.isPrimary) {
  const numCPUs = availableParallelism();

  console.log(`Primary ${process.pid} is running`);
  console.log(`Starting ${numCPUs} workers...`);

  for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
  import("./server");
}


================================================
FILE: examples/instance/clustering/server.ts
================================================
import { server } from "kitojs";

const app = server({
  reusePort: true, // this is required for clustering
});

app.get("/", ({ res }) => res.send("hello world!"));

app.listen(3000, () => {
  console.log(`Worker ${process.pid} listening on port 3000`);
});


================================================
FILE: examples/instance/extend.ts
================================================
import { server } from "kitojs";

interface Extends {
  user: { id: string; name: string };
}

const app = server().extend<Extends>((ctx) => {
  ctx.user = { id: "1", name: "Neo" };
});

app.get("/", ({ res, user }) => {
  res.json({ user });
});

app.listen(3000);


================================================
FILE: examples/instance/file.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/download", ({ res }) => {
  res.sendFile("public/banner.png", {
    root: "./",
    maxAge: 3600,
    lastModified: true,
    cacheControl: true,
    immutable: false,
    etag: true,
  });
});

app.get("/export", ({ res }) => {
  res.download("public/banner.png", "kito-banner.png");
});

app.listen(3000);


================================================
FILE: examples/instance/middlewares/index.ts
================================================
import { server } from "kitojs";

import { auth } from "./samples/auth";
import { logger } from "./samples/logger";

const app = server();
app.use(logger);

app.get("/", auth, ({ res }) => {
  res.send("hello world!");
});

app.listen(3000);


================================================
FILE: examples/instance/middlewares/samples/auth.ts
================================================
import { middleware } from "kitojs";

export const auth = middleware((ctx, next) => {
  const { req, res } = ctx;
  const header = req.headers.authorization;

  if (header && header === "Bearer secret_token") {
    return next();
  }

  res.status(401).send("unauthorized");
});


================================================
FILE: examples/instance/middlewares/samples/logger.ts
================================================
import { middleware } from "kitojs";

export const logger = middleware((ctx, next) => {
  const { method, url } = ctx.req;
  const date = new Date().toISOString();

  console.log(`[${date}] ${method} ${url}`);
  return next();
});


================================================
FILE: examples/instance/params.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/:id", ({ req, res }) => {
  res.send(req.params.id);
});

app.get("/multi/:id/:name", ({ req, res }) => {
  const { id, name } = req.params;
  res.json({ id, name });
});

app.listen(3000);


================================================
FILE: examples/instance/route.ts
================================================
import { server } from "kitojs";

const app = server();
const routes = app.route("/");

routes.get(({ res }) => {
  res.send("hello world!");
});

routes.post(({ req, res }) => {
  res.json({ body: req.body });
});

app.get("/bye", ({ res }) => {
  res.send("bye!");
});

app.listen(3000);


================================================
FILE: examples/instance/router/cats.ts
================================================
import { router } from "kitojs";

const cats = router();

cats.get("/", ({ res }) => {
  res.send("hello cats!");
});

cats.post("/", ({ res }) => {
  res.json({ msg: "cat created!" });
});

export default cats;


================================================
FILE: examples/instance/router/index.ts
================================================
import { server } from "kitojs";
import cats from "./cats";

const app = server();
app.mount("/cats", cats);

app.get("/", ({ res }) => {
  res.send("hello world!");
});

app.listen(3000);


================================================
FILE: examples/instance/schemas/builder.ts
================================================
import { schema, server, t } from "kitojs";

const app = server();

const userSchema = schema({
  params: t.object({ id: t.str().uuid() }),
  query: t.object({ limit: t.num().max(100) }),
  body: t.object({ name: t.str().min(1) }),
});

app.post(
  "/users/:id",
  ({ req, res }) => {
    // types are automatically inferred from userSchema
    const { id } = req.params;
    const { limit } = req.query;
    const { name } = req.body;

    res.json({ id, limit, name });
  },
  userSchema,
);

app.listen(3000);


================================================
FILE: examples/instance/schemas/json.ts
================================================
import { schema, server } from "kitojs";

const app = server();

const userSchema = schema.json({
  params: {
    type: "object",
    properties: {
      id: { type: "string", format: "uuid" },
    },
    required: ["id"],
  },
  query: {
    type: "object",
    properties: {
      limit: { type: "number", maximum: 100 },
    },
    required: ["limit"],
  },
  body: {
    type: "object",
    properties: {
      name: { type: "string", minLength: 1 },
    },
    required: ["name"],
  },
});

app.post(
  "/users/:id",
  ({ req, res }) => {
    // types are automatically inferred from userSchema
    const { id } = req.params;
    const { limit } = req.query;
    const { name } = req.body;

    res.json({ id, limit, name });
  },
  userSchema,
);

app.listen(3000);


================================================
FILE: examples/instance/streaming/sse.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/", ({ res }) => {
  const sse = res.sse();

  sse.send("hello world!");

  sse.send(
    {
      msg: "this is a message",
    },
    "message",
  );

  sse.close();
});

app.listen(3000);


================================================
FILE: examples/instance/streaming/stream.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/", ({ res }) => {
  const stream = res.stream();

  stream.write("Chunk 1\n");

  setTimeout(() => {
    stream.write("Chunk 2\n");
  }, 1000);

  setTimeout(() => {
    stream.end("Final chunk\n");
  }, 2000);
});

app.listen(3000);


================================================
FILE: examples/instance/unixSocket.ts
================================================
import { server } from "kitojs";

const app = server();

app.get("/", ({ res }) => {
  res.send("Hello from Unix socket!");
});

app.listen({ unixSocket: "./app.sock" });


================================================
FILE: examples/package.json
================================================
{
  "name": "@kitojs/examples",
  "description": "Kito's usage examples.",
  "private": true,
  "type": "module",

  "scripts": {
    "ex:run": "tsx runExample.ts"
  },

  "dependencies": {
    "kitojs": "workspace:*"
  },
  "devDependencies": {
    "tsx": "^4.20.6",
    "typescript": "^5.9.2"
  }
}


================================================
FILE: examples/runExample.ts
================================================
#!/usr/bin/env tsx

import { existsSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));

const args = process.argv.slice(2);
let style: string | undefined;
let example: string | undefined;

for (let i = 0; i < args.length; i++) {
  if (args[i] === "--style" && i + 1 < args.length) {
    style = args[i + 1];
    i++;
  } else if (args[i] === "--example" && i + 1 < args.length) {
    example = args[i + 1];
    i++;
  }
}

if (!style || !example) {
  console.error(
    "Usage: pnpm ex:run --style <fluent|instance> --example <example-name>",
  );
  console.error("\nExamples:");
  console.error("  pnpm ex:run --style fluent --example basic");
  console.error("  pnpm ex:run --style fluent --example router");
  console.error("  pnpm ex:run --style fluent --example schemas/builder");
  process.exit(1);
}

if (style !== "fluent" && style !== "instance") {
  console.error(`Invalid style: ${style}. Must be 'fluent' or 'instance'.`);
  process.exit(1);
}

let filePath: string;

const dirWithIndex = resolve(__dirname, style, example, "index.ts");
if (existsSync(dirWithIndex)) {
  filePath = dirWithIndex;
} else {
  const directFile = resolve(__dirname, style, `${example}.ts`);
  if (existsSync(directFile)) {
    filePath = directFile;
  } else {
    console.error(`Example not found: ${style}/${example}`);
    console.error(`Tried: ${dirWithIndex} and ${directFile}`);
    process.exit(1);
  }
}

console.log(`Running example: ${style}/${example}`);
import(filePath);


================================================
FILE: examples/tsconfig.json
================================================
{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {},
  "include": ["instance/**/*", "fluent/**/*"],
  "references": [
    {
      "path": "../packages/kitojs"
    }
  ]
}


================================================
FILE: lefthook.yml
================================================
skip_output:
  - meta
  - summary

pre-commit:
  parallel: true
  commands:
    # Rust commands
    fmt-check:
      tags: rust formatter
      run: cargo fmt --all -- --check
      fail_text: "Code is not formatted. Run 'cargo fmt' to fix."

    clippy:
      tags: rust linter
      run: cargo clippy --all-targets --all-features -- -D warnings
      fail_text: "Linting failed. Fix clippy warnings."

    check:
      tags: rust compile
      run: cargo check --all-targets --all-features
      fail_text: "Code doesn't compile. Fix compilation errors."

    # TypeScript commands
    biome-check:
      tags: js formatter linter
      glob: "*.{js,ts,tsx,json,jsonc}"
      run: pnpm biome check --write {staged_files}
      stage_fixed: true
      fail_text: "JS/TS formatting/linting failed. Fix biome issues."

    
    # ts-typecheck:
      # tags: typescript checker
      # glob: "*.{ts,tsx}"
      # run: pnpm tsc --noEmit
      # fail_text: "TypeScript type checking failed. Fix type errors."

pre-push:
  parallel: false
  commands:
    # Rust tests
    test:
      tags: rust test
      run: cargo test --all-features
      fail_text: "Rust tests failed. Fix failing tests before pushing."

    # Security audits
    audit:
      tags: rust security
      run: cargo audit
      fail_text: "Security vulnerabilities found. Run 'cargo audit fix' or update dependencies."
      skip:
        - merge
        - rebase

    npm-audit:
      tags: npm security
      run: pnpm audit --audit-level moderate
      fail_text: "NPM security vulnerabilities found. Run 'pnpm audit --fix'."
      skip:
        - merge
        - rebase

prepare-commit-msg:
  commands:
    conventional-commits-prepare:
      tags: commit-msg
      run: |
        # This hook runs before the commit message is created
        # We can use it to prepare or validate the template
        echo "📝 Preparing commit message validation..."
        echo "Remember to use Conventional Commits format: <type>[optional scope]: <description>"

commit-msg:
  commands:
    conventional-commits:
      tags: commit-msg
      run: |
        #!/bin/sh

        # Try to extract commit message
        commit_msg=""

        # 1. Argument (standard for commit-msg hook)
        if [ -n "$1" ] && [ -f "$1" ]; then
          commit_msg="$(head -n 1 "$1" | tr -d '\r\n')"
        fi

        # 2. Lefthook-provided variable
        if [ -z "$commit_msg" ] && [ -n "$LEFTHOOK_COMMIT_MSG" ]; then
          commit_msg="$(echo "$LEFTHOOK_COMMIT_MSG" | head -n 1 | tr -d '\r\n')"
        fi

        # 3. Git fallback
        if [ -z "$commit_msg" ] && [ -f ".git/COMMIT_EDITMSG" ]; then
          commit_msg="$(head -n 1 .git/COMMIT_EDITMSG | tr -d '\r\n')"
        fi

        # Skip empty or comment-only messages
        if [ -z "$commit_msg" ] || echo "$commit_msg" | grep -qE '^#'; then
          echo "⚠️  Empty commit message or comment, skipping validation."
          exit 0
        fi

        echo "🔍 Validating commit message: \"$commit_msg\""

        # Check Conventional Commit pattern
        if ! echo "$commit_msg" | grep -qE '^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([^)]+\))?: .{1,50}$'; then
          echo "❌ Invalid commit message format!"
          echo "Format: <type>[optional scope]: <description>"
          echo "Types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test"
          echo "Example: feat(auth): add login functionality"
          echo "Your message: \"$commit_msg\""
          exit 1
        fi

        # Length check
        if [ "${#commit_msg}" -gt 72 ]; then
          echo "❌ Commit message too long! Keep it under 72 characters."
          echo "Length: ${#commit_msg}"
          echo "Your message: \"$commit_msg\""
          exit 1
        fi

        # Imperative mood check
        description="$(echo "$commit_msg" | sed -E 's/^[a-z]+(\([^)]+\))?: //')"
        if echo "$description" | grep -qE '^(added|fixed|updated|changed|removed|created)'; then
          echo "⚠️  Use imperative mood (add, fix, update), not past tense"
          echo "Example: 'feat: add auth' not 'feat: added auth'"
          echo "Your message: \"$commit_msg\""
          exit 1
        fi

        echo "✅ Commit message is valid!"
      fail_text: "Commit message doesn't follow Conventional Commits specification."

post-checkout:
  commands:
    cargo-update:
      tags: rust dependencies
      files: git diff --name-only HEAD@{1} HEAD
      glob: "{Cargo.toml,Cargo.lock}"
      run: |
        echo "🔄 Cargo files changed, updating dependencies..."
        cargo check
      skip:
        - merge
        - rebase

    npm-install:
      tags: npm dependencies
      files: git diff --name-only HEAD@{1} HEAD
      glob: "{package.json,pnpm-lock.yaml,pnpm-workspace.yaml}"
      run: |
        echo "🔄 NPM files changed, updating dependencies..."
        pnpm install
      skip:
        - merge
        - rebase

post-merge:
  commands:
    cargo-check:
      tags: rust post-merge
      run: |
        echo "🔄 Running cargo check after merge..."
        cargo check
        echo "✅ Rust dependencies updated successfully"

    npm-check:
      tags: npm post-merge
      run: |
        echo "🔄 Running npm check after merge..."
        pnpm install --frozen-lockfile
        echo "✅ NPM dependencies updated successfully"

colors: true
no_tty: false
source_dir: ".lefthook"
source_dir_local: ".lefthook-local"

output:
  - execution
  - execution_out
  - execution_info
  - skips

================================================
FILE: license
================================================
MIT License

Copyright (c) 2024 kitojs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: package.json
================================================
{
  "name": "kito",
  "version": "1.0.0",
  "description": "The Kito's workspace.",
  "scripts": {
    "fmt": "biome format",
    "fmt:fix": "biome format --write",
    "lint": "biome lint",
    "lint:fix": "biome lint --write",
    "check": "biome check",
    "check:fix": "biome check --write",

    "build": "pnpm core:build --platform && pnpm ts:build",
    "core:build": "pnpm --filter @kitojs/kito-core build",
    "ts:build": "pnpm --filter @kitojs/types build && pnpm --filter kitojs build",

    "dev": "pnpm -r dev",
    "test": "pnpm -r test",

    "ex:run": "pnpm --filter examples ex:run",
    "bench:run": "pnpm --filter bench bench:run"
  },
  "author": "Nehuén <github.com/nehu3n>",
  "license": "MIT",
  "devDependencies": {
    "@biomejs/biome": "2.2.3",
    "@types/node": "^24.5.2",
    "typescript": "^5.9.2"
  }
}


================================================
FILE: packages/core/.gitignore
================================================
dist/

================================================
FILE: packages/core/Cargo.toml
================================================
[package]
name = "core"
version = "0.1.0"
edition = "2024"

[lib]
name = "core"
crate-type = ["cdylib"]

[dependencies]
napi = { version = "3.2.4", default-features = false, features = ["async"] }
napi-derive = "3.2.4"
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", features = ["full"] }
once_cell = "1.21.3"
dashmap = "6.1.0"
urlencoding = "2.1.3"
httpdate = "1.0.3"
parking_lot = "0.12.5"
serde = { version = "1.0.228", features = ["derive"] }
regex = "1.12.2"
serde_json = "1.0.145"
matchit = "0.9.0"
ahash = "0.8.12"
base64 = "0.22.1"
socket2 = "0.6.1"
futures-util = "0.3.31"

[dev-dependencies]
tokio-test = "0.4.4"

[build-dependencies]
napi-build = "2.2.3"


================================================
FILE: packages/core/build.rs
================================================
fn main() {
    napi_build::setup();
}


================================================
FILE: packages/core/package.json
================================================
{
  "name": "@kitojs/kito-core",
  "version": "1.0.0-alpha.8",
  "description": "Internal logic (core) of the Kito framework written in Rust.",
  "scripts": {
    "build": "napi build --release --esm --const-enum --output-dir dist",
    "test": "cargo test"
  },

  "dependencies": {},
  "devDependencies": {
    "@napi-rs/cli": "^3.1.5"
  },

  "type": "module",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "files": [
    "dist"
  ],

  "napi": {
    "binaryName": "core",
    "packageName": "@kitojs/kito-core",
    "targets": [
      "x86_64-apple-darwin",
      "aarch64-apple-darwin",
      "x86_64-unknown-linux-gnu",
      "x86_64-pc-windows-msvc",
      "x86_64-unknown-linux-musl",
      "aarch64-unknown-linux-gnu",
      "i686-pc-windows-msvc",
      "armv7-unknown-linux-gnueabihf",
      "aarch64-linux-android",
      "x86_64-unknown-freebsd",
      "aarch64-unknown-linux-musl",
      "aarch64-pc-windows-msvc",
      "armv7-linux-androideabi"
    ]
  },
  "engines": {
    "node": ">= 10"
  }
}


================================================
FILE: packages/core/src/http/cookies.rs
================================================
#[derive(Clone, Default)]
#[napi(object)]
pub struct CookieOptionsCore {
    pub domain: Option<String>,
    pub http_only: Option<bool>,
    pub max_age: Option<i32>,
    pub path: Option<String>,
    pub secure: Option<bool>,
    pub signed: Option<bool>,
    pub same_site: Option<String>,
}

pub fn serialize_cookie(name: &str, value: &str, options: &CookieOptionsCore) -> String {
    let mut cookie = format!("{name}={value}");

    if let Some(max_age) = options.max_age {
        cookie.push_str(&format!("; Max-Age={max_age}"));
    }

    if let Some(ref path) = options.path {
        cookie.push_str(&format!("; Path={path}"));
    } else {
        cookie.push_str("; Path=/");
    }

    if let Some(ref domain) = options.domain {
        cookie.push_str(&format!("; Domain={domain}"));
    }

    if options.http_only.unwrap_or(false) {
        cookie.push_str("; HttpOnly");
    }

    if options.secure.unwrap_or(false) {
        cookie.push_str("; Secure");
    }

    if let Some(ref same_site) = options.same_site {
        cookie.push_str(&format!("; SameSite={same_site}"));
    }

    cookie
}


================================================
FILE: packages/core/src/http/cookies_tests.rs
================================================
#[cfg(test)]
mod tests {
    use super::super::cookies::*;

    #[test]
    fn test_basic_cookie() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: None,
            max_age: None,
            path: None,
            secure: None,
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("session", "abc123", &options);
        assert!(result.contains("session=abc123"));
        assert!(result.contains("Path=/"));
    }

    #[test]
    fn test_cookie_with_max_age() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: None,
            max_age: Some(3600),
            path: None,
            secure: None,
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("token", "xyz", &options);
        assert!(result.contains("Max-Age=3600"));
    }

    #[test]
    fn test_cookie_with_custom_path() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: None,
            max_age: None,
            path: Some("/admin".to_string()),
            secure: None,
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("admin", "secret", &options);
        assert!(result.contains("Path=/admin"));
    }

    #[test]
    fn test_cookie_with_domain() {
        let options = CookieOptionsCore {
            domain: Some("example.com".to_string()),
            http_only: None,
            max_age: None,
            path: None,
            secure: None,
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("user", "john", &options);
        assert!(result.contains("Domain=example.com"));
    }

    #[test]
    fn test_cookie_http_only() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: Some(true),
            max_age: None,
            path: None,
            secure: None,
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("secure", "data", &options);
        assert!(result.contains("HttpOnly"));
    }

    #[test]
    fn test_cookie_secure() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: None,
            max_age: None,
            path: None,
            secure: Some(true),
            signed: None,
            same_site: None,
        };

        let result = serialize_cookie("token", "value", &options);
        assert!(result.contains("Secure"));
    }

    #[test]
    fn test_cookie_same_site() {
        let options = CookieOptionsCore {
            domain: None,
            http_only: None,
            max_age: None,
            path: None,
            secure: None,
            signed: None,
            same_site: Some("Strict".to_string()),
        };

        let result = serialize_cookie("csrf", "token", &options);
        assert!(result.contains("SameSite=Strict"));
    }

    #[test]
    fn test_cookie_all_options() {
        let options = CookieOptionsCore {
            domain: Some("example.com".to_string()),
            http_only: Some(true),
            max_age: Some(7200),
            path: Some("/api".to_string()),
            secure: Some(true),
            signed: None,
            same_site: Some("Lax".to_string()),
        };

        let result = serialize_cookie("full", "options", &options);

        assert!(result.contains("full=options"));
        assert!(result.contains("Max-Age=7200"));
        assert!(result.contains("Path=/api"));
        assert!(result.contains("Domain=example.com"));
        assert!(result.contains("HttpOnly"));
        assert!(result.contains("Secure"));
        assert!(result.contains("SameSite=Lax"));
    }
}


================================================
FILE: packages/core/src/http/files.rs
================================================
use hyper::body::Bytes;

use std::{collections::HashMap, time::UNIX_EPOCH};
use tokio::{fs::File, io::AsyncReadExt};

use crate::http::mime::get_mime_type;
use crate::http::response::SendFileOptionsCore;

pub async fn read_file_for_response(
    path: &str,
    options: Option<SendFileOptionsCore>,
) -> Result<(Bytes, HashMap<String, String>), std::io::Error> {
    let full_path = if let Some(ref opts) = options {
        if let Some(ref root) = opts.root { format!("{root}/{path}") } else { path.to_string() }
    } else {
        path.to_string()
    };

    let mut file = File::open(&full_path).await?;
    let metadata = file.metadata().await?;
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).await?;

    let mut headers = HashMap::new();
    headers.insert("Content-Type".to_string(), get_mime_type(path).to_string());
    headers.insert("Content-Length".to_string(), metadata.len().to_string());

    if let Some(opts) = options {
        if let Some(ref custom_headers) = opts.headers {
            headers.extend(custom_headers.clone());
        }

        if opts.last_modified.unwrap_or(true)
            && let Ok(modified) = metadata.modified()
            && let Ok(duration) = modified.duration_since(UNIX_EPOCH)
        {
            headers.insert(
                "Last-Modified".to_string(),
                httpdate::fmt_http_date(UNIX_EPOCH + duration),
            );
        }

        if opts.cache_control.unwrap_or(true)
            && let Some(max_age) = opts.max_age
        {
            let cache_value = if opts.immutable.unwrap_or(false) {
                format!("public, max-age={max_age}, immutable")
            } else {
                format!("public, max-age={max_age}")
            };
            headers.insert("Cache-Control".to_string(), cache_value);
        }

        if opts.accept_ranges.unwrap_or(true) {
            headers.insert("Accept-Ranges".to_string(), "bytes".to_string());
        }
    }

    Ok((Bytes::from(contents), headers))
}


================================================
FILE: packages/core/src/http/mime.rs
================================================
use std::path::Path;

pub fn get_mime_type(path: &str) -> &'static str {
    let extension = Path::new(path).extension().and_then(|e| e.to_str()).unwrap_or("");

    match extension.to_lowercase().as_str() {
        "html" | "htm" => "text/html",
        "css" => "text/css",
        "js" | "mjs" => "application/javascript",
        "json" => "application/json",
        "xml" => "application/xml",
        "txt" => "text/plain",
        "png" => "image/png",
        "jpg" | "jpeg" => "image/jpeg",
        "gif" => "image/gif",
        "svg" => "image/svg+xml",
        "webp" => "image/webp",
        "ico" => "image/x-icon",
        "pdf" => "application/pdf",
        "zip" => "application/zip",
        "wasm" => "application/wasm",
        "mp4" => "video/mp4",
        "webm" => "video/webm",
        "mp3" => "audio/mpeg",
        "wav" => "audio/wav",
        "woff" | "woff2" => "font/woff2",
        "ttf" => "font/ttf",
        "otf" => "font/otf",
        _ => "application/octet-stream",
    }
}


================================================
FILE: packages/core/src/http/mime_tests.rs
================================================
#[cfg(test)]
mod tests {
    use super::super::mime::get_mime_type;

    #[test]
    fn test_html_mime_types() {
        assert_eq!(get_mime_type("index.html"), "text/html");
        assert_eq!(get_mime_type("page.htm"), "text/html");
    }

    #[test]
    fn test_css_mime_type() {
        assert_eq!(get_mime_type("styles.css"), "text/css");
    }

    #[test]
    fn test_javascript_mime_types() {
        assert_eq!(get_mime_type("app.js"), "application/javascript");
        assert_eq!(get_mime_type("module.mjs"), "application/javascript");
    }

    #[test]
    fn test_json_mime_type() {
        assert_eq!(get_mime_type("data.json"), "application/json");
    }

    #[test]
    fn test_image_mime_types() {
        assert_eq!(get_mime_type("photo.png"), "image/png");
        assert_eq!(get_mime_type("photo.jpg"), "image/jpeg");
        assert_eq!(get_mime_type("photo.jpeg"), "image/jpeg");
        assert_eq!(get_mime_type("icon.gif"), "image/gif");
        assert_eq!(get_mime_type("logo.svg"), "image/svg+xml");
        assert_eq!(get_mime_type("image.webp"), "image/webp");
    }

    #[test]
    fn test_font_mime_types() {
        assert_eq!(get_mime_type("font.woff"), "font/woff2");
        assert_eq!(get_mime_type("font.woff2"), "font/woff2");
        assert_eq!(get_mime_type("font.ttf"), "font/ttf");
        assert_eq!(get_mime_type("font.otf"), "font/otf");
    }

    #[test]
    fn test_video_mime_types() {
        assert_eq!(get_mime_type("video.mp4"), "video/mp4");
        assert_eq!(get_mime_type("video.webm"), "video/webm");
    }

    #[test]
    fn test_audio_mime_types() {
        assert_eq!(get_mime_type("song.mp3"), "audio/mpeg");
        assert_eq!(get_mime_type("sound.wav"), "audio/wav");
    }

    #[test]
    fn test_default_mime_type() {
        assert_eq!(get_mime_type("file.unknown"), "application/octet-stream");
        assert_eq!(get_mime_type("no_extension"), "application/octet-stream");
    }

    #[test]
    fn test_case_insensitive() {
        assert_eq!(get_mime_type("FILE.HTML"), "text/html");
        assert_eq!(get_mime_type("IMAGE.PNG"), "image/png");
        assert_eq!(get_mime_type("Script.JS"), "application/javascript");
    }

    #[test]
    fn test_path_with_directories() {
        assert_eq!(get_mime_type("/path/to/file.html"), "text/html");
        assert_eq!(get_mime_type("../assets/image.png"), "image/png");
    }
}


================================================
FILE: packages/core/src/http/request.rs
================================================
use http_body_util::BodyExt;
use hyper::{
    Request,
    body::{Bytes, Incoming},
};

use napi::bindgen_prelude::{Buffer, External};

use std::{collections::HashMap, net::SocketAddr, sync::Arc};

#[derive(Clone)]
pub struct RequestCore {
    pub method: String,
    pub url: String,
    pub pathname: String,
    pub search: Option<String>,
    pub protocol: String,
    pub hostname: String,
    pub original_url: String,
    pub secure: bool,
    pub xhr: bool,
    pub ip: String,
    pub ips: Vec<String>,

    pub body: Bytes,
    pub headers_raw: HashMap<String, String>,
    pub params: HashMap<String, String>,
    pub query_raw: HashMap<String, Vec<String>>,
    pub cookies_raw: HashMap<String, String>,
}

impl RequestCore {
    pub async fn new(
        req: Request<Incoming>,
        remote_addr: Option<SocketAddr>,
        trust_proxy: bool,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        let method = req.method().as_str().to_string();
        let uri = req.uri();
        let url = uri.to_string();
        let pathname = uri.path().to_string();
        let search = uri.query().map(|q| format!("?{q}"));
        let original_url = url.clone();

        let mut headers_raw = HashMap::with_capacity(req.headers().len());
        for (name, value) in req.headers() {
            if let Ok(v) = value.to_str() {
                headers_raw.insert(name.as_str().to_string(), v.to_string());
            }
        }

        let mut query_raw: HashMap<String, Vec<String>> = HashMap::new();
        if let Some(q) = uri.query() {
            for pair in q.split('&') {
                if let Some((key, value)) = pair.split_once('=') {
                    let decoded_key = urlencoding::decode(key).unwrap_or_default().into_owned();
                    let decoded_value = urlencoding::decode(value).unwrap_or_default().into_owned();
                    query_raw.entry(decoded_key).or_default().push(decoded_value);
                }
            }
        }

        let scheme = req.uri().scheme_str().unwrap_or("http").to_string();

        let body = req.into_body().collect().await?.to_bytes();

        let protocol = if trust_proxy {
            headers_raw
                .get("x-forwarded-proto")
                .map(|s| s.to_string())
                .unwrap_or_else(|| "http".to_string())
        } else {
            scheme
        };

        let secure = protocol.eq_ignore_ascii_case("https");
        let hostname = headers_raw.get("host").cloned().unwrap_or_else(|| "localhost".to_string());

        let cookies_raw = headers_raw.get("cookie").map_or(HashMap::new(), |cookie_str| {
            cookie_str
                .split(';')
                .filter_map(|c| {
                    let parts: Vec<&str> = c.trim().splitn(2, '=').collect();
                    if parts.len() == 2 {
                        Some((parts[0].to_string(), parts[1].to_string()))
                    } else {
                        None
                    }
                })
                .collect()
        });

        let ips: Vec<String> = if trust_proxy {
            headers_raw
                .get("x-forwarded-for")
                .map(|s| s.split(',').map(|ip| ip.trim().to_string()).collect())
                .unwrap_or_default()
        } else {
            vec![]
        };

        let ip = ips
            .first()
            .cloned()
            .or_else(|| remote_addr.map(|a| a.ip().to_string()))
            .unwrap_or_default();

        let xhr =
            headers_raw.get("x-requested-with").map(|v| v == "XMLHttpRequest").unwrap_or(false);

        Ok(Self {
            method,
            url,
            pathname,
            search,
            protocol,
            hostname,
            original_url,
            secure,
            xhr,
            ip,
            ips,
            body,
            headers_raw,
            params: HashMap::new(),
            query_raw,
            cookies_raw,
        })
    }
}

#[napi]
pub fn get_body_buffer(core: &External<Arc<RequestCore>>) -> Buffer {
    Buffer::from(core.body.as_ref())
}

#[napi]
pub fn get_header(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {
    core.headers_raw.get(&name.to_lowercase()).cloned()
}

#[napi]
pub fn get_all_headers(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {
    core.headers_raw.clone()
}

#[napi]
pub fn get_query_param(core: &External<Arc<RequestCore>>, name: String) -> Option<Vec<String>> {
    core.query_raw.get(&name).cloned()
}

#[napi]
pub fn get_all_query(core: &External<Arc<RequestCore>>) -> HashMap<String, Vec<String>> {
    core.query_raw.clone()
}

#[napi]
pub fn get_param(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {
    core.params.get(&name).cloned()
}

#[napi]
pub fn get_all_params(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {
    core.params.clone()
}

#[napi]
pub fn get_cookie(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {
    core.cookies_raw.get(&name).cloned()
}

#[napi]
pub fn get_all_cookies(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {
    core.cookies_raw.clone()
}

#[napi]
pub fn get_method(core: &External<Arc<RequestCore>>) -> String {
    core.method.clone()
}

#[napi]
pub fn get_url(core: &External<Arc<RequestCore>>) -> String {
    core.url.clone()
}

#[napi]
pub fn get_pathname(core: &External<Arc<RequestCore>>) -> String {
    core.pathname.clone()
}

#[napi]
pub fn get_search(core: &External<Arc<RequestCore>>) -> Option<String> {
    core.search.clone()
}

#[napi]
pub fn get_protocol(core: &External<Arc<RequestCore>>) -> String {
    core.protocol.clone()
}

#[napi]
pub fn get_hostname(core: &External<Arc<RequestCore>>) -> String {
    core.hostname.clone()
}

#[napi]
pub fn get_ip(core: &External<Arc<RequestCore>>) -> String {
    core.ip.clone()
}

#[napi]
pub fn get_ips(core: &External<Arc<RequestCore>>) -> Vec<String> {
    core.ips.clone()
}

#[napi]
pub fn get_secure(core: &External<Arc<RequestCore>>) -> bool {
    core.secure
}

#[napi]
pub fn get_xhr(core: &External<Arc<RequestCore>>) -> bool {
    core.xhr
}


================================================
FILE: packages/core/src/http/response.rs
================================================
use http_body_util::{Full, StreamBody, combinators::BoxBody};
use hyper::body::{Bytes, Frame};

use napi::bindgen_prelude::{Buffer, External};

use parking_lot::Mutex;
use serde_json::from_slice;

use std::{collections::HashMap, sync::Arc};
use tokio::sync::mpsc::UnboundedSender;

pub struct ResponseChannel {
    pub tx: Mutex<Option<UnboundedSender<ResponseMessage>>>,
}

impl ResponseChannel {
    pub fn new(tx: UnboundedSender<ResponseMessage>) -> Self {
        Self { tx: Mutex::new(Some(tx)) }
    }
}

pub enum ResponseMessage {
    Complete { status: u16, headers: Vec<(String, String)>, body: Bytes },
    StreamStart { status: u16, headers: Vec<(String, String)> },
    StreamChunk { data: Bytes },
    StreamEnd,
}

pub enum ResponseBody {
    Full(Full<Bytes>),
    Stream(StreamBody<Frame<Bytes>>),
}

pub type BoxedBody = BoxBody<Bytes, Box<dyn std::error::Error + Send + Sync>>;

/// buffer: [status_code(2)] [headers_len(4)] [headers_json] [body]
#[napi]
pub fn send_response(channel: &External<Arc<ResponseChannel>>, buffer: Buffer) -> napi::Result<()> {
    let data = buffer.as_ref();

    if data.len() < 6 {
        return Err(napi::Error::from_reason("Invalid response buffer"));
    }

    let status_code = u16::from_le_bytes([data[0], data[1]]);

    let headers_len = u32::from_le_bytes([data[2], data[3], data[4], data[5]]) as usize;

    if data.len() < 6 + headers_len {
        return Err(napi::Error::from_reason("Invalid headers length"));
    }

    let headers_json = &data[6..6 + headers_len];
    let headers: Vec<(String, String)> = from_slice(headers_json)
        .map_err(|e| napi::Error::from_reason(format!("Invalid headers JSON: {e}")))?;

    let body_start = 6 + headers_len;
    let body = if body_start < data.len() {
        Bytes::copy_from_slice(&data[body_start..])
    } else {
        Bytes::new()
    };

    let mut tx_guard = channel.tx.lock();
    if let Some(tx) = tx_guard.as_ref() {
        let _ = tx.send(ResponseMessage::Complete { status: status_code, headers, body });
        *tx_guard = None;
        Ok(())
    } else {
        Err(napi::Error::from_reason("Response already sent"))
    }
}

/// buffer: [status_code(2)] [headers_len(4)] [headers_json]
#[napi]
pub fn start_stream(channel: &External<Arc<ResponseChannel>>, buffer: Buffer) -> napi::Result<()> {
    let data = buffer.as_ref();

    if data.len() < 6 {
        return Err(napi::Error::from_reason("Invalid stream start buffer"));
    }

    let status_code = u16::from_le_bytes([data[0], data[1]]);
    let headers_len = u32::from_le_bytes([data[2], data[3], data[4], data[5]]) as usize;

    if data.len() < 6 + headers_len {
        return Err(napi::Error::from_reason("Invalid headers length"));
    }

    let headers_json = &data[6..6 + headers_len];
    let headers: Vec<(String, String)> = from_slice(headers_json)
        .map_err(|e| napi::Error::from_reason(format!("Invalid headers JSON: {e}")))?;

    let tx_guard = channel.tx.lock();
    if let Some(tx) = tx_guard.as_ref() {
        let _ = tx.send(ResponseMessage::StreamStart { status: status_code, headers });
        Ok(())
    } else {
        Err(napi::Error::from_reason("Response already sent"))
    }
}

#[napi]
pub fn send_chunk(channel: &External<Arc<ResponseChannel>>, data: Buffer) -> napi::Result<()> {
    let tx_guard = channel.tx.lock();
    if let Some(tx) = tx_guard.as_ref() {
        let bytes = Bytes::copy_from_slice(data.as_ref());
        let _ = tx.send(ResponseMessage::StreamChunk { data: bytes });
        Ok(())
    } else {
        Err(napi::Error::from_reason("Stream not started"))
    }
}

#[napi]
pub fn end_stream(channel: &External<Arc<ResponseChannel>>) -> napi::Result<()> {
    let mut tx_guard = channel.tx.lock();
    if let Some(tx) = tx_guard.take() {
        let _ = tx.send(ResponseMessage::StreamEnd);
        Ok(())
    } else {
        Err(napi::Error::from_reason("Stream already ended"))
    }
}

#[derive(Clone)]
#[napi(object)]
pub struct SendFileOptionsCore {
    pub max_age: Option<u32>,
    pub root: Option<String>,
    pub last_modified: Option<bool>,
    pub headers: Option<HashMap<String, String>>,
    pub dotfiles: Option<String>,
    pub accept_ranges: Option<bool>,
    pub cache_control: Option<bool>,
    pub immutable: Option<bool>,
}


================================================
FILE: packages/core/src/http.rs
================================================
pub mod cookies;
pub mod cookies_tests;
pub mod files;
pub mod mime;
pub mod mime_tests;
pub mod request;
pub mod response;


================================================
FILE: packages/core/src/lib.rs
================================================
#[macro_use]
extern crate napi_derive;

pub mod http;
pub mod server;
pub mod validation;


================================================
FILE: packages/core/src/server/context.rs
================================================
use crate::http::{request::RequestCore, response::ResponseChannel};
use napi::{
    Env,
    bindgen_prelude::{External, Object, ToNapiValue},
    sys,
};
use std::sync::Arc;

pub struct ContextObject {
    pub req: External<Arc<RequestCore>>,
    pub res: External<Arc<ResponseChannel>>,
}

impl ToNapiValue for ContextObject {
    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> napi::Result<sys::napi_value> {
        let mut obj = Object::new(&Env::from_raw(env))?;
        obj.set("req", val.req)?;
        obj.set("res", val.res)?;
        unsafe { Object::to_napi_value(env, obj) }
    }
}


================================================
FILE: packages/core/src/server/core.rs
================================================
use hyper::server::conn::http1;
use hyper_util::rt::TokioIo;

use napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};
use napi_derive::napi;

use std::net::SocketAddr;
use tokio::{net::TcpListener, sync::watch};

#[cfg(unix)]
use std::fs;
#[cfg(unix)]
use std::path::Path;
#[cfg(unix)]
use tokio::net::UnixListener;

use crate::server::{handler::handle_request, routes::insert_route};

use super::routes::Route;

#[derive(Clone)]
#[napi(object)]
pub struct ServerOptionsCore {
    pub port: Option<u16>,
    pub host: Option<String>,
    pub unix_socket: Option<String>,
    pub trust_proxy: Option<bool>,
    pub max_request_size: Option<u32>,
    pub timeout: Option<u32>,
    pub reuse_port: Option<bool>,
}

#[napi]
pub struct ServerCore {
    config: ServerOptionsCore,
    shutdown_tx: Option<watch::Sender<()>>,
}

#[napi]
impl ServerCore {
    #[napi(constructor)]
    pub fn new(config: ServerOptionsCore) -> Self {
        ServerCore { config, shutdown_tx: None }
    }

    #[napi]
    pub fn get_config(&self) -> ServerOptionsCore {
        self.config.clone()
    }

    #[napi]
    pub fn set_config(&mut self, config: ServerOptionsCore) {
        self.config = config;
    }

    #[napi]
    pub fn add_route(&mut self, route: Route) -> napi::Result<()> {
        insert_route(route)
    }

    /// Start the HTTP server on TCP or Unix socket and execute the `ready` callback if provided.
    ///
    /// # Safety
    ///
    /// This function is unsafe because it exposes logic that will be called from JavaScript via N-API, and depends on:
    /// - The `ServerCore` object remains alive while async tasks are running.
    /// - The `ThreadsafeFunction` passed (if it exists) is valid and has not been released.
    /// - `start` is not called twice simultaneously on the same instance.
    ///
    /// The caller must guarantee these conditions.
    #[napi(ts_args_type = "ready: (() => void) | undefined")]
    pub async unsafe fn start(&mut self, ready: Option<ThreadsafeFunction<()>>) {
        let (shutdown_tx, mut shutdown_rx) = watch::channel::<()>(());
        self.shutdown_tx = Some(shutdown_tx);

        #[cfg(unix)]
        if let Some(ref socket_path) = self.config.unix_socket {
            self.start_unix_socket(socket_path, ready, &mut shutdown_rx).await;
            return;
        }

        self.start_tcp(ready, &mut shutdown_rx).await;
    }

    async fn start_tcp(
        &self,
        ready: Option<ThreadsafeFunction<()>>,
        shutdown_rx: &mut watch::Receiver<()>,
    ) {
        let port = self.config.port.unwrap_or(3000);
        let host = self.config.host.as_deref().unwrap_or("0.0.0.0");
        let addr: SocketAddr = format!("{host}:{port}").parse().expect("Invalid address");

        let listener = create_reusable_listener(addr).await.expect("Failed to create listener");

        if let Some(ready_cb) = ready {
            ready_cb.call(Ok(()), ThreadsafeFunctionCallMode::NonBlocking);
        }

        loop {
            tokio::select! {
                Ok((tcp, remote_addr)) = listener.accept() => {
                    let io = TokioIo::new(tcp);
                    let config = self.config.clone();

                    tokio::spawn(async move {
                        if let Err(err) = http1::Builder::new()
                            .serve_connection(io, hyper::service::service_fn(move |req| {
                                handle_request(req, config.clone(), Some(remote_addr))
                            }))
                            .await
                        {
                            eprintln!("Error serving connection: {err:?}");
                        }
                    });
                },
                _ = shutdown_rx.changed() => break,
            }
        }
    }

    #[cfg(unix)]
    async fn start_unix_socket(
        &self,
        socket_path: &str,
        ready: Option<ThreadsafeFunction<()>>,
        shutdown_rx: &mut watch::Receiver<()>,
    ) {
        let path = Path::new(socket_path);

        if path.exists() {
            fs::remove_file(path).unwrap_or_else(|e| {
                eprintln!("Warning: Could not remove existing socket file: {e}");
            });
        }

        let listener = UnixListener::bind(path).expect("Failed to bind Unix socket");

        if let Some(ready_cb) = ready {
            ready_cb.call(Ok(()), ThreadsafeFunctionCallMode::NonBlocking);
        }

        loop {
            tokio::select! {
                Ok((stream, _)) = listener.accept() => {
                    let io = TokioIo::new(stream);
                    let config = self.config.clone();

                    tokio::spawn(async move {
                        if let Err(err) = http1::Builder::new()
                            .serve_connection(io, hyper::service::service_fn(move |req| {
                                handle_request(req, config.clone(), None)
                            }))
                            .await
                        {
                            eprintln!("Error serving connection: {err:?}");
                        }
                    });
                },
                _ = shutdown_rx.changed() => break,
            }
        }

        let _ = fs::remove_file(path);
    }

    #[napi]
    pub fn close(&self) {
        if let Some(tx) = &self.shutdown_tx {
            let _ = tx.send(());
        }
    }
}

async fn create_reusable_listener(addr: SocketAddr) -> std::io::Result<TcpListener> {
    use socket2::{Domain, Protocol, Socket, Type};
    use std::net::TcpListener as StdListener;

    let domain = if addr.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 };
    let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;

    socket.set_reuse_address(true)?;

    #[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))]
    socket.set_reuse_port(true)?;

    socket.set_nonblocking(true)?;
    socket.bind(&addr.into())?;
    socket.listen(1024)?;

    let std_listener: StdListener = socket.into();
    TcpListener::from_std(std_listener)
}


================================================
FILE: packages/core/src/server/handler.rs
================================================
use http_body_util::{BodyExt, Full, StreamBody};
use hyper::{
    Request, Response,
    body::{Bytes, Frame, Incoming},
    header::{HeaderName, HeaderValue},
};

use napi::{bindgen_prelude::External, threadsafe_function::ThreadsafeFunctionCallMode};
use serde_json::json;

use futures_util::stream;
use std::{convert::Infallible, net::SocketAddr, sync::Arc};
use tokio::sync::mpsc;

use crate::{
    http::{
        request::RequestCore,
        response::{BoxedBody, ResponseChannel, ResponseMessage},
    },
    server::{
        context::ContextObject,
        core::ServerOptionsCore,
        routes::{ROUTER, ResponseStrategy},
    },
    validation::parser::*,
};

pub async fn handle_request(
    req: Request<Incoming>,
    config: ServerOptionsCore,
    remote_addr: Option<SocketAddr>,
) -> Result<Response<BoxedBody>, std::convert::Infallible> {
    let method = req.method().to_string();
    let pathname = req.uri().path().to_string();

    let matched = match ROUTER.find(&method, &pathname) {
        Some(m) => m,
        None => {
            return Ok(Response::builder()
                .status(404)
                .body(
                    Full::new(Bytes::from_static(b"Not Found"))
                        .map_err(|never| match never {})
                        .boxed(),
                )
                .unwrap());
        }
    };

    let route = matched.route;

    if let ResponseStrategy::FullStatic(ref response) = route.strategy {
        let (parts, body) = response.clone().into_parts();
        let body_bytes = body.collect().await.unwrap().to_bytes();
        return Ok(Response::from_parts(
            parts,
            Full::new(body_bytes).map_err(|never| match never {}).boxed(),
        ));
    }

    if let ResponseStrategy::ParamTemplate { ref template, ref params, ref headers } =
        route.strategy
    {
        let mut rendered = template.clone();

        for param_name in params {
            if let Some(value) = matched.params.get(param_name) {
                let placeholder = format!("{{{{params.{param_name}}}}}");
                rendered = rendered.replace(&placeholder, value);
            }
        }

        let mut response = Response::builder().status(200);
        for (name, value) in headers {
            response = response.header(name.as_str(), value.as_str());
        }

        return Ok(response
            .body(Full::new(Bytes::from(rendered)).map_err(|never| match never {}).boxed())
            .unwrap());
    }

    let mut req_core =
        match RequestCore::new(req, remote_addr, config.trust_proxy.unwrap_or(false)).await {
            Ok(core) => core,
            Err(e) => {
                eprintln!("Error creating request: {e}");
                return Ok(Response::builder()
                    .status(400)
                    .body(
                        Full::new(Bytes::from_static(b"Bad Request"))
                            .map_err(|never| match never {})
                            .boxed(),
                    )
                    .unwrap());
            }
        };

    req_core.params = matched.params.into_iter().collect();

    if let Some(schema) = &route.schema {
        if let Some(params_schema) = &schema.params
            && let Err(e) = parse_params(&req_core.params, params_schema)
        {
            let error_msg = format!("Validation error in {}: {}", e.field, e.message);
            return Ok(Response::builder()
                .status(400)
                .header("Content-Type", "application/json")
                .body(
                    Full::new(Bytes::from(
                        json!({
                            "error": "Validation Error",
                            "message": error_msg
                        })
                        .to_string(),
                    ))
                    .map_err(|never| match never {})
                    .boxed(),
                )
                .unwrap());
        }

        if let Some(query_schema) = &schema.query
            && let Err(e) = parse_query(&req_core.query_raw, query_schema)
        {
            let error_msg = format!("Validation error in {}: {}", e.field, e.message);
            return Ok(Response::builder()
                .status(400)
                .header("Content-Type", "application/json")
                .body(
                    Full::new(Bytes::from(
                        json!({
                            "error": "Validation Error",
                            "message": error_msg
                        })
                        .to_string(),
                    ))
                    .map_err(|never| match never {})
                    .boxed(),
                )
                .unwrap());
        }

        if let Some(body_schema) = &schema.body {
            let has_body_method = matches!(method.as_str(), "POST" | "PUT" | "PATCH" | "DELETE");

            if has_body_method {
                if req_core.body.is_empty() {
                    let error_msg = "Request body is required".to_string();
                    return Ok(Response::builder()
                        .status(400)
                        .header("Content-Type", "application/json")
                        .body(
                            Full::new(Bytes::from(
                                json!({
                                    "error": "Validation Error",
                                    "message": error_msg
                                })
                                .to_string(),
                            ))
                            .map_err(|never| match never {})
                            .boxed(),
                        )
                        .unwrap());
                }

                if let Err(e) = parse_body(req_core.body.as_ref(), body_schema) {
                    let error_msg = format!("Validation error in {}: {}", e.field, e.message);
                    return Ok(Response::builder()
                        .status(400)
                        .header("Content-Type", "application/json")
                        .body(
                            Full::new(Bytes::from(
                                json!({
                                    "error": "Validation Error",
                                    "message": error_msg
                                })
                                .to_string(),
                            ))
                            .map_err(|never| match never {})
                            .boxed(),
                        )
                        .unwrap());
                }
            }
        }

        if let Some(headers_schema) = &schema.headers
            && let Err(e) = parse_headers(&req_core.headers_raw, headers_schema)
        {
            let error_msg = format!("Validation error in {}: {}", e.field, e.message);
            return Ok(Response::builder()
                .status(400)
                .header("Content-Type", "application/json")
                .body(
                    Full::new(Bytes::from(
                        json!({
                            "error": "Validation Error",
                            "message": error_msg
                        })
                        .to_string(),
                    ))
                    .map_err(|never| match never {})
                    .boxed(),
                )
                .unwrap());
        }
    }

    let (response_tx, mut response_rx) = mpsc::unbounded_channel();
    let res_builder = Arc::new(ResponseChannel::new(response_tx));

    let ctx_obj = ContextObject {
        req: External::new(Arc::new(req_core)),
        res: External::new(res_builder.clone()),
    };

    if let ResponseStrategy::Dynamic(handler) = route.strategy.clone() {
        let _ = handler.call(ctx_obj, ThreadsafeFunctionCallMode::NonBlocking);
    }

    if let Some(first_msg) = response_rx.recv().await {
        match first_msg {
            ResponseMessage::Complete { status, headers, body } => {
                let mut response = Response::builder().status(status);

                for (name, value) in headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (name.parse::<HeaderName>(), value.parse::<HeaderValue>())
                    {
                        response = response.header(header_name, header_value);
                    }
                }

                return Ok(response
                    .body(Full::new(body).map_err(|never| match never {}).boxed())
                    .unwrap());
            }
            ResponseMessage::StreamStart { status, headers } => {
                let mut response = Response::builder().status(status);

                for (name, value) in headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (name.parse::<HeaderName>(), value.parse::<HeaderValue>())
                    {
                        response = response.header(header_name, header_value);
                    }
                }

                let stream = stream::unfold(response_rx, |mut rx| async move {
                    match rx.recv().await {
                        Some(ResponseMessage::StreamChunk { data }) => {
                            Some((Ok(Frame::data(data)), rx))
                        }
                        Some(ResponseMessage::StreamEnd) | None => None,
                        _ => None,
                    }
                });

                let body = StreamBody::new(stream);
                return Ok(response
                    .body(body.map_err(|never: Infallible| match never {}).boxed())
                    .unwrap());
            }
            _ => {}
        }
    }

    Ok(Response::builder()
        .status(200)
        .body(Full::new(Bytes::new()).map_err(|never| match never {}).boxed())
        .unwrap())
}


================================================
FILE: packages/core/src/server/router.rs
================================================
use ahash::AHashMap;
use matchit::{Match, Router as MatchitRouter};
use parking_lot::RwLock;
use std::sync::Arc;

use super::routes::CompiledRoute;

pub struct TrieRouter {
    inner: MatchitRouter<Arc<CompiledRoute>>,
}

impl Default for TrieRouter {
    fn default() -> Self {
        Self::new()
    }
}

impl TrieRouter {
    pub fn new() -> Self {
        Self { inner: MatchitRouter::new() }
    }

    pub fn insert(&mut self, path: &str, route: Arc<CompiledRoute>) -> Result<(), String> {
        self.inner.insert(path, route).map_err(|e| format!("Failed to insert route: {e}"))
    }

    pub fn find<'a>(&'a self, path: &'a str) -> Option<Match<'a, 'a, &'a Arc<CompiledRoute>>> {
        self.inner.at(path).ok()
    }
}

pub struct HttpRouter {
    static_routes: AHashMap<Box<str>, Arc<CompiledRoute>>,
    dynamic_routes: TrieRouter,
}

impl Default for HttpRouter {
    fn default() -> Self {
        Self::new()
    }
}

impl HttpRouter {
    pub fn new() -> Self {
        Self { static_routes: AHashMap::new(), dynamic_routes: TrieRouter::new() }
    }

    pub fn insert(&mut self, route: CompiledRoute) -> Result<(), String> {
        let route_arc = Arc::new(route);

        if Self::is_static_route(&route_arc.path) {
            self.static_routes.insert(route_arc.path.clone(), route_arc.clone());
        } else {
            self.dynamic_routes.insert(&route_arc.path, route_arc.clone())?;
        }

        Ok(())
    }

    pub fn find<'a>(&'a self, path: &'a str) -> Option<RouteMatch> {
        if let Some(route) = self.static_routes.get(path) {
            return Some(RouteMatch { route: route.clone(), params: AHashMap::new() });
        }

        if let Some(matched) = self.dynamic_routes.find(path) {
            let mut params = AHashMap::new();

            for (key, value) in matched.params.iter() {
                params.insert(key.to_string(), value.to_string());
            }

            return Some(RouteMatch { route: matched.value.clone(), params });
        }

        None
    }

    fn is_static_route(path: &str) -> bool {
        !path.contains(':') && !path.contains('*') && !path.contains('{')
    }
}

pub struct RouteMatch {
    pub route: Arc<CompiledRoute>,
    pub params: AHashMap<String, String>,
}

pub struct GlobalRouter {
    routers: RwLock<AHashMap<Box<str>, HttpRouter>>,
}

impl Default for GlobalRouter {
    fn default() -> Self {
        Self::new()
    }
}

impl GlobalRouter {
    pub fn new() -> Self {
        Self { routers: RwLock::new(AHashMap::new()) }
    }

    pub fn insert(&self, method: &str, route: CompiledRoute) -> Result<(), String> {
        let mut routers = self.routers.write();
        let router = routers.entry(method.to_string().into_boxed_str()).or_default();

        router.insert(route)
    }

    pub fn find(&self, method: &str, path: &str) -> Option<RouteMatch> {
        let routers = self.routers.read();

        if let Some(router) = routers.get(method) {
            return router.find(path);
        }

        None
    }

    pub fn route_count(&self) -> usize {
        let routers = self.routers.read();
        routers.values().map(|r| r.static_routes.len()).sum()
    }
}


================================================
FILE: packages/core/src/server/routes.rs
================================================
use ahash::HashMap;
use std::sync::Arc;

use http_body_util::Full;
use hyper::Response;
use hyper::body::Bytes;

use napi::Error;
use napi::{bindgen_prelude::Function, threadsafe_function::ThreadsafeFunction};

use base64::Engine;
use base64::engine::general_purpose;

use once_cell::sync::Lazy;
use serde_json::{Value, from_str, from_value};

use crate::server::context::ContextObject;
use crate::server::router::GlobalRouter;
use crate::validation::types::SchemaType;

pub type RouteHandler = ThreadsafeFunction<ContextObject, (), ContextObject, napi::Status, false>;

pub struct CompiledRoute {
    pub method: Box<str>,
    pub path: Box<str>,
    pub segments: Box<[Box<str>]>,
    pub strategy: ResponseStrategy,
    pub schema: Option<RouteSchema>,
}

#[derive(Clone)]
pub struct RouteSchema {
    pub params: Option<SchemaType>,
    pub query: Option<SchemaType>,
    pub body: Option<SchemaType>,
    pub headers: Option<SchemaType>,
}

pub static ROUTER: Lazy<GlobalRouter> = Lazy::new(GlobalRouter::new);

#[napi(object)]
pub struct Route {
    pub path: String,
    #[napi(ts_type = "'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'TRACE'")]
    pub method: String,
    #[napi(ts_type = "RouteHandler")]
    pub handler: Function<'static, ContextObject, ()>,
    pub schema: Option<String>,
    pub static_response: Option<String>,
}

#[derive(Clone)]
pub enum ResponseStrategy {
    Dynamic(Arc<RouteHandler>),
    FullStatic(Response<Full<Bytes>>),
    ParamTemplate { template: String, params: Vec<String>, headers: HashMap<String, String> },
}

fn convert_path_to_matchit_format(path: &str) -> String {
    if !path.contains(':') {
        return path.to_string();
    }

    let parts: Vec<&str> = path.split('/').collect();
    let converted_parts: Vec<String> = parts
        .iter()
        .map(|part| {
            if let Some(stripped) = part.strip_prefix(':') {
                format!("{{{stripped}}}")
            } else {
                part.to_string()
            }
        })
        .collect();

    converted_parts.join("/")
}

pub fn insert_route(route: Route) -> napi::Result<()> {
    let method_key: Box<str> = route.method.clone().into_boxed_str();
    let converted_path = convert_path_to_matchit_format(&route.path);

    let segments: Vec<Box<str>> = converted_path
        .split('/')
        .filter(|s| !s.is_empty())
        .map(|s| s.to_string().into_boxed_str())
        .collect();

    let strategy = if let Some(static_json) = route.static_response {
        let static_info: Value = from_str(&static_json)
            .map_err(|e| Error::from_reason(format!("Invalid static response: {e}")))?;

        match static_info["type"].as_str() {
            Some("full_static") => {
                let status = static_info["status"].as_u64().unwrap_or(200) as u16;

                let body_base64 = static_info["body"]
                    .as_str()
                    .ok_or_else(|| Error::from_reason("Missing body field in static response"))?;

                let body_bytes = general_purpose::STANDARD
                    .decode(body_base64)
                    .map_err(|e| Error::from_reason(format!("Invalid base64 body: {e}")))?;

                let mut response = Response::builder().status(status);

                if let Some(headers) = static_info["headers"].as_object() {
                    for (name, value) in headers {
                        if let Some(v) = value.as_str() {
                            response = response.header(name.as_str(), v);
                        }
                    }
                }

                let response = response
                    .body(Full::new(Bytes::from(body_bytes)))
                    .map_err(|e| Error::from_reason(format!("Failed to build response: {e}")))?;

                ResponseStrategy::FullStatic(response)
            }
            Some("param_template") => {
                let template = static_info["template"]
                    .as_str()
                    .ok_or_else(|| Error::from_reason("Missing template field"))?
                    .to_string();

                let params: Vec<String> = static_info["params"]
                    .as_array()
                    .ok_or_else(|| Error::from_reason("Missing params field"))?
                    .iter()
                    .filter_map(|v| v.as_str().map(|s| s.to_string()))
                    .collect();

                let headers: HashMap<String, String> = static_info["headers"]
                    .as_object()
                    .ok_or_else(|| Error::from_reason("Missing headers field"))?
                    .iter()
                    .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
                    .collect();

                ResponseStrategy::ParamTemplate { template, params, headers }
            }
            _ => {
                let tsfn = route.handler.build_threadsafe_function().build()?;
                ResponseStrategy::Dynamic(Arc::new(tsfn))
            }
        }
    } else {
        let tsfn = route.handler.build_threadsafe_function().build()?;
        ResponseStrategy::Dynamic(Arc::new(tsfn))
    };

    let schema = if let Some(schema_json) = route.schema {
        let parsed: Value = from_str(&schema_json)
            .map_err(|e| Error::from_reason(format!("Invalid schema JSON: {e}")))?;

        Some(RouteSchema {
            params: parsed.get("params").and_then(|v| from_value(v.clone()).ok()),
            query: parsed.get("query").and_then(|v| from_value(v.clone()).ok()),
            body: parsed.get("body").and_then(|v| from_value(v.clone()).ok()),
            headers: parsed.get("headers").and_then(|v| from_value(v.clone()).ok()),
        })
    } else {
        None
    };

    let compiled = CompiledRoute {
        method: method_key.clone(),
        path: converted_path.into_boxed_str(),
        segments: segments.into_boxed_slice(),
        strategy,
        schema,
    };

    ROUTER.insert(&route.method, compiled).map_err(Error::from_reason)?;
    Ok(())
}


================================================
FILE: packages/core/src/server.rs
================================================
pub mod context;
pub mod core;
pub mod handler;
pub mod router;
pub mod routes;

pub use core::ServerCore;
pub use router::{GlobalRouter, HttpRouter};
pub use routes::{CompiledRoute, ROUTER, Route};


================================================
FILE: packages/core/src/validation/parser.rs
================================================
use serde_json::{Map, Value, from_slice};

use super::types::*;
use crate::validation::validate_value;

use std::collections::HashMap;

pub fn parse_params(
    params: &HashMap<String, String>,
    schema: &SchemaType,
) -> Result<Value, ValidationError> {
    let mut obj = Map::new();
    for (key, value) in params {
        obj.insert(key.clone(), Value::String(value.clone()));
    }

    validate_value(&Value::Object(obj), schema, "params")
}

pub fn parse_query(
    query: &HashMap<String, Vec<String>>,
    schema: &SchemaType,
) -> Result<Value, ValidationError> {
    let mut obj = Map::new();
    for (key, values) in query {
        if values.len() == 1 {
            obj.insert(key.clone(), Value::String(values[0].clone()));
        } else if values.is_empty() {
            obj.insert(key.clone(), Value::Null);
        } else {
            let arr: Vec<Value> = values.iter().map(|v| Value::String(v.clone())).collect();
            obj.insert(key.clone(), Value::Array(arr));
        }
    }

    validate_value(&Value::Object(obj), schema, "query")
}

pub fn parse_body(body: &[u8], schema: &SchemaType) -> Result<Value, ValidationError> {
    if body.is_empty() {
        if let SchemaType::Object { optional: true, default, .. } = schema {
            return Ok(default.clone().unwrap_or(Value::Null));
        }
        return Err(ValidationError::new("body", "Request body is required"));
    }

    let body_value: Value =
        from_slice(body).map_err(|_| ValidationError::new("body", "Invalid JSON"))?;

    validate_value(&body_value, schema, "body")
}

pub fn parse_headers(
    headers: &HashMap<String, String>,
    schema: &SchemaType,
) -> Result<Value, ValidationError> {
    let mut obj = Map::new();
    for (key, value) in headers {
        obj.insert(key.clone(), Value::String(value.clone()));
    }

    validate_value(&Value::Object(obj), schema, "headers")
}


================================================
FILE: packages/core/src/validation/parser_tests.rs
================================================
#[cfg(test)]
mod tests {
    use super::super::parser::*;
    use super::super::types::*;
    use serde_json::json;
    use std::collections::HashMap;

    #[test]
    fn test_parse_params_basic() {
        let mut params = HashMap::new();
        params.insert("id".to_string(), "123".to_string());
        params.insert("name".to_string(), "john".to_string());

        let mut shape = HashMap::new();
        shape.insert(
            "id".to_string(),
            SchemaType::String { optional: false, default: None, constraints: vec![] },
        );
        shape.insert(
            "name".to_string(),
            SchemaType::String { optional: false, default: None, constraints: vec![] },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_params(&params, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_query_single_value() {
        let mut query = HashMap::new();
        query.insert("page".to_string(), vec!["1".to_string()]);

        let mut shape = HashMap::new();
        shape.insert(
            "page".to_string(),
            SchemaType::Number { optional: false, default: None, constraints: vec![] },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_query(&query, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_query_multiple_values() {
        let mut query = HashMap::new();
        query.insert("tags".to_string(), vec!["rust".to_string(), "web".to_string()]);

        let mut shape = HashMap::new();
        shape.insert(
            "tags".to_string(),
            SchemaType::Array {
                optional: false,
                default: None,
                constraints: vec![],
                item: Box::new(SchemaType::String {
                    optional: false,
                    default: None,
                    constraints: vec![],
                }),
            },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_query(&query, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_body_valid_json() {
        let body = br#"{"name":"Alice","age":25}"#;

        let mut shape = HashMap::new();
        shape.insert(
            "name".to_string(),
            SchemaType::String { optional: false, default: None, constraints: vec![] },
        );
        shape.insert(
            "age".to_string(),
            SchemaType::Number { optional: false, default: None, constraints: vec![] },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_body(body, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_body_invalid_json() {
        let body = b"not valid json";

        let schema = SchemaType::Object { optional: false, default: None, shape: HashMap::new() };

        let result = parse_body(body, &schema);
        assert!(result.is_err());
    }

    #[test]
    fn test_parse_body_empty_with_optional() {
        let body = b"";

        let schema =
            SchemaType::Object { optional: true, default: Some(json!({})), shape: HashMap::new() };

        let result = parse_body(body, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_body_empty_required() {
        let body = b"";

        let schema = SchemaType::Object { optional: false, default: None, shape: HashMap::new() };

        let result = parse_body(body, &schema);
        assert!(result.is_err());
    }

    #[test]
    fn test_parse_headers() {
        let mut headers = HashMap::new();
        headers.insert("authorization".to_string(), "Bearer token123".to_string());
        headers.insert("content-type".to_string(), "application/json".to_string());

        let mut shape = HashMap::new();
        shape.insert(
            "authorization".to_string(),
            SchemaType::String { optional: false, default: None, constraints: vec![] },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_headers(&headers, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_params_with_validation() {
        let mut params = HashMap::new();
        params.insert("id".to_string(), "550e8400-e29b-41d4-a716-446655440000".to_string());

        let mut shape = HashMap::new();
        shape.insert(
            "id".to_string(),
            SchemaType::String {
                optional: false,
                default: None,
                constraints: vec![StringConstraint::Uuid],
            },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_params(&params, &schema);
        assert!(result.is_ok());
    }

    #[test]
    fn test_parse_params_validation_fails() {
        let mut params = HashMap::new();
        params.insert("id".to_string(), "not-a-uuid".to_string());

        let mut shape = HashMap::new();
        shape.insert(
            "id".to_string(),
            SchemaType::String {
                optional: false,
                default: None,
                constraints: vec![StringConstraint::Uuid],
            },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let result = parse_params(&params, &schema);
        assert!(result.is_err());
    }
}


================================================
FILE: packages/core/src/validation/tests.rs
================================================
#[cfg(test)]
mod tests {
    use super::super::{types::*, validators::*};
    use serde_json::{Value, json};
    use std::collections::HashMap;

    #[test]
    fn test_string_min_length() {
        let constraints = vec![StringConstraint::Min { value: 5 }];

        assert!(validate_string("hello", &constraints).is_ok());
        assert!(validate_string("hi", &constraints).is_err());
    }

    #[test]
    fn test_string_max_length() {
        let constraints = vec![StringConstraint::Max { value: 5 }];

        assert!(validate_string("hello", &constraints).is_ok());
        assert!(validate_string("hello world", &constraints).is_err());
    }

    #[test]
    fn test_string_email() {
        let constraints = vec![StringConstraint::Email];

        assert!(validate_string("user@example.com", &constraints).is_ok());
        assert!(validate_string("invalid-email", &constraints).is_err());
        assert!(validate_string("no@domain", &constraints).is_err());
    }

    #[test]
    fn test_string_uuid() {
        let constraints = vec![StringConstraint::Uuid];

        assert!(validate_string("550e8400-e29b-41d4-a716-446655440000", &constraints).is_ok());
        assert!(validate_string("not-a-uuid", &constraints).is_err());
    }

    #[test]
    fn test_number_min() {
        let constraints = vec![NumberConstraint::Min { value: 10.0 }];

        assert!(validate_number(15.0, &constraints).is_ok());
        assert!(validate_number(5.0, &constraints).is_err());
    }

    #[test]
    fn test_number_max() {
        let constraints = vec![NumberConstraint::Max { value: 100.0 }];

        assert!(validate_number(50.0, &constraints).is_ok());
        assert!(validate_number(150.0, &constraints).is_err());
    }

    #[test]
    fn test_number_int() {
        let constraints = vec![NumberConstraint::Int];

        assert!(validate_number(42.0, &constraints).is_ok());
        assert!(validate_number(42.5, &constraints).is_err());
    }

    #[test]
    fn test_number_positive() {
        let constraints = vec![NumberConstraint::Positive];

        assert!(validate_number(10.0, &constraints).is_ok());
        assert!(validate_number(-5.0, &constraints).is_err());
        assert!(validate_number(0.0, &constraints).is_err());
    }

    #[test]
    fn test_validate_string_value() {
        let schema = SchemaType::String {
            optional: false,
            default: None,
            constraints: vec![StringConstraint::Min { value: 3 }],
        };

        assert!(validate_value(&json!("hello"), &schema, "field").is_ok());
        assert!(validate_value(&json!("hi"), &schema, "field").is_err());
        assert!(validate_value(&Value::Null, &schema, "field").is_err());
    }

    #[test]
    fn test_validate_optional_with_default() {
        let schema = SchemaType::String {
            optional: true,
            default: Some("default".to_string()),
            constraints: vec![],
        };

        let result = validate_value(&Value::Null, &schema, "field").unwrap();
        assert_eq!(result, json!("default"));
    }

    #[test]
    fn test_validate_number_from_string() {
        let schema = SchemaType::Number { optional: false, default: None, constraints: vec![] };

        assert!(validate_value(&json!("42"), &schema, "field").is_ok());
        assert!(validate_value(&json!("not-a-number"), &schema, "field").is_err());
    }

    #[test]
    fn test_validate_boolean_from_string() {
        let schema = SchemaType::Boolean { optional: false, default: None };

        assert_eq!(validate_value(&json!("true"), &schema, "field").unwrap(), json!(true));
        assert_eq!(validate_value(&json!("false"), &schema, "field").unwrap(), json!(false));
        assert_eq!(validate_value(&json!("1"), &schema, "field").unwrap(), json!(true));
        assert_eq!(validate_value(&json!("0"), &schema, "field").unwrap(), json!(false));
    }

    #[test]
    fn test_validate_array() {
        let item_schema =
            SchemaType::Number { optional: false, default: None, constraints: vec![] };

        let schema = SchemaType::Array {
            optional: false,
            default: None,
            constraints: vec![ArrayConstraint::Min { value: 2 }],
            item: Box::new(item_schema),
        };

        assert!(validate_value(&json!([1, 2, 3]), &schema, "field").is_ok());
        assert!(validate_value(&json!([1]), &schema, "field").is_err());
    }

    #[test]
    fn test_validate_object() {
        let mut shape = HashMap::new();
        shape.insert(
            "name".to_string(),
            SchemaType::String { optional: false, default: None, constraints: vec![] },
        );
        shape.insert(
            "age".to_string(),
            SchemaType::Number {
                optional: false,
                default: None,
                constraints: vec![NumberConstraint::Positive],
            },
        );

        let schema = SchemaType::Object { optional: false, default: None, shape };

        let valid_value = json!({
            "name": "Alice",
            "age": 25
        });

        let invalid_value = json!({
            "name": "Bob",
            "age": -5
        });

        assert!(validate_value(&valid_value, &schema, "field").is_ok());
        assert!(validate_value(&invalid_value, &schema, "field").is_err());
    }

    #[test]
    fn test_validate_literal() {
        let schema = SchemaType::Literal { optional: false, default: None, value: json!("admin") };

        assert!(validate_value(&json!("admin"), &schema, "field").is_ok());
        assert!(validate_value(&json!("user"), &schema, "field").is_err());
    }

    #[test]
    fn test_validate_union() {
        let schemas = vec![
            SchemaType::String { optional: false, default: None, constraints: vec![] },
            SchemaType::Number { optional: false, default: None, constraints: vec![] },
        ];

        let schema = SchemaType::Union { optional: false, default: None, schemas };

        assert!(validate_value(&json!("hello"), &schema, "field").is_ok());
        assert!(validate_value(&json!(42), &schema, "field").is_ok());
        assert!(validate_value(&json!(true), &schema, "field").is_err());
    }
}


================================================
FILE: packages/core/src/validation/types.rs
================================================
use serde::{Deserialize, Serialize};
use serde_json::Value;

use std::collections::HashMap;

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum SchemaType {
    String {
        optional: bool,
        default: Option<String>,
        constraints: Vec<StringConstraint>,
    },
    Number {
        optional: bool,
        default: Option<f64>,
        constraints: Vec<NumberConstraint>,
    },
    Boolean {
        optional: bool,
        default: Option<bool>,
    },
    Array {
        optional: bool,
        default: Option<Value>,
        constraints: Vec<ArrayConstraint>,
        item: Box<SchemaType>,
    },
    Object {
        optional: bool,
        default: Option<Value>,
        shape: HashMap<String, SchemaType>,
    },
    Literal {
        optional: bool,
        default: Option<Value>,
        value: Value,
    },
    Union {
        optional: bool,
        default: Option<Value>,
        schemas: Vec<SchemaType>,
    },
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum StringConstraint {
    Min { value: usize },
    Max { value: usize },
    Length { value: usize },
    Email,
    Url,
    Uuid,
    Regex { value: String },
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum NumberConstraint {
    Min { value: f64 },
    Max { value: f64 },
    Int,
    Positive,
    Negative,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum ArrayConstraint {
    Min { value: usize },
    Max { value: usize },
    Length { value: usize },
}

#[derive(Debug, Clone)]
pub struct ValidationError {
    pub field: String,
    pub message: String,
}

impl ValidationError {
    pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
        Self { field: field.into(), message: message.into() }
    }
}


================================================
FILE: packages/core/src/validation/validators.rs
================================================
use super::types::*;

use regex::Regex;
use serde_json::{Map, Number, Value};

pub fn validate_string(
    value: &str,
    constraints: &[StringConstraint],
) -> Result<(), ValidationError> {
    let uuid_regex = Regex::new(
        r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
    )
    .unwrap();
    let email_regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();

    for constraint in constraints {
        match constraint {
            StringConstraint::Min { value: min } => {
                if value.len() < *min {
                    return Err(ValidationError::new(
                        "",
                        format!("String must be at least {min} characters long"),
                    ));
                }
            }
            StringConstraint::Max { value: max } => {
                if value.len() > *max {
                    return Err(ValidationError::new(
                        "",
                        format!("String must be at most {max} characters long"),
                    ));
                }
            }
            StringConstraint::Length { value: length } => {
                if value.len() != *length {
                    return Err(ValidationError::new(
                        "",
                        format!("String must be exactly {length} characters long"),
                    ));
                }
            }
            StringConstraint::Email => {
                if !email_regex.is_match(value) {
                    return Err(ValidationError::new("", "Invalid email format"));
                }
            }
            StringConstraint::Url => {
                if !value.starts_with("http://") && !value.starts_with("https://") {
                    return Err(ValidationError::new("", "Invalid URL format"));
                }
            }
            StringConstraint::Uuid => {
                if !uuid_regex.is_match(value) {
                    return Err(ValidationError::new("", "Invalid UUID format"));
                }
            }
            StringConstraint::Regex { value: pattern } => {
                let regex = Regex::new(pattern)
                    .map_err(|_| ValidationError::new("", "Invalid regex pattern"))?;

                if !regex.is_match(value) {
                    return Err(ValidationError::new("", "String does not match pattern"));
                }
            }
        }
    }
    Ok(())
}

pub fn validate_number(
    value: f64,
    constraints: &[NumberConstraint],
) -> Result<(), ValidationError> {
    for constraint in constraints {
        match constraint {
            NumberConstraint::Min { value: min } => {
                if value < *min {
                    return Err(ValidationError::new("", format!("Number must be at least {min}")));
                }
            }
            NumberConstraint::Max { value: max } => {
                if value > *max {
                    return Err(ValidationError::new("", format!("Number must be at most {max}")));
                }
            }
            NumberConstraint::Int => {
                if value.fract() != 0.0 {
                    return Err(ValidationError::new("", "Number must be an integer"));
                }
            }
            NumberConstraint::Positive => {
                if value <= 0.0 {
                    return Err(ValidationError::new("", "Number must be positive"));
                }
            }
            NumberConstraint::Negative => {
                if value >= 0.0 {
                    return Err(ValidationError::new("", "Number must be negative"));
                }
            }
        }
    }
    Ok(())
}

pub fn validate_value(
    value: &Value,
    schema: &SchemaType,
    field_path: &str,
) -> Result<Value, ValidationError> {
    match schema {
        SchemaType::String { optional, default, constraints } => {
            if value.is_null() {
                if *optional {
                    return Ok(default
                        .as_ref()
                        .map(|d| Value::String(d.clone()))
                        .unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            let str_value = value
                .as_str()
                .ok_or_else(|| ValidationError::new(field_path, "Expected string"))?;

            validate_string(str_value, constraints)
                .map_err(|e| ValidationError::new(field_path, e.message))?;

            Ok(value.clone())
        }
        SchemaType::Number { optional, default, constraints } => {
            if value.is_null() {
                if *optional {
                    return Ok(default
                        .as_ref()
                        .map(|d| Value::Number(Number::from_f64(*d).unwrap()))
                        .unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            let num_value = if let Some(n) = value.as_f64() {
                n
            } else if let Some(s) = value.as_str() {
                s.parse::<f64>()
                    .map_err(|_| ValidationError::new(field_path, "Invalid number format"))?
            } else {
                return Err(ValidationError::new(field_path, "Expected number"));
            };

            validate_number(num_value, constraints)
                .map_err(|e| ValidationError::new(field_path, e.message))?;

            Ok(Value::Number(Number::from_f64(num_value).unwrap()))
        }
        SchemaType::Boolean { optional, default } => {
            if value.is_null() {
                if *optional {
                    return Ok(default.as_ref().map(|d| Value::Bool(*d)).unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            if let Some(b) = value.as_bool() {
                Ok(Value::Bool(b))
            } else if let Some(s) = value.as_str() {
                match s.to_lowercase().as_str() {
                    "true" | "1" => Ok(Value::Bool(true)),
                    "false" | "0" => Ok(Value::Bool(false)),
                    _ => Err(ValidationError::new(field_path, "Invalid boolean value")),
                }
            } else {
                Err(ValidationError::new(field_path, "Expected boolean"))
            }
        }
        SchemaType::Array { optional, default, constraints, item } => {
            if value.is_null() {
                if *optional {
                    return Ok(default.clone().unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            let arr = value
                .as_array()
                .ok_or_else(|| ValidationError::new(field_path, "Expected array"))?;

            for constraint in constraints {
                match constraint {
                    ArrayConstraint::Min { value: min } => {
                        if arr.len() < *min {
                            return Err(ValidationError::new(
                                field_path,
                                format!("Array must have at least {min} items"),
                            ));
                        }
                    }
                    ArrayConstraint::Max { value: max } => {
                        if arr.len() > *max {
                            return Err(ValidationError::new(
                                field_path,
                                format!("Array must have at most {max} items"),
                            ));
                        }
                    }
                    ArrayConstraint::Length { value: length } => {
                        if arr.len() != *length {
                            return Err(ValidationError::new(
                                field_path,
                                format!("Array must have exactly {length} items"),
                            ));
                        }
                    }
                }
            }

            let mut validated_items = Vec::new();
            for (i, item_value) in arr.iter().enumerate() {
                let item_path = format!("{field_path}[{i}]");
                let validated = validate_value(item_value, item, &item_path)?;
                validated_items.push(validated);
            }

            Ok(Value::Array(validated_items))
        }
        SchemaType::Object { optional, default, shape } => {
            if value.is_null() || (value.is_object() && value.as_object().unwrap().is_empty()) {
                if *optional {
                    return Ok(default.clone().unwrap_or(Value::Null));
                }

                if shape.is_empty() {
                    return Ok(Value::Object(Map::new()));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            let obj = value
                .as_object()
                .ok_or_else(|| ValidationError::new(field_path, "Expected object"))?;

            let mut validated_obj = Map::new();

            for (key, field_schema) in shape {
                let field_value = obj.get(key).cloned().unwrap_or(Value::Null);
                let new_path =
                    if field_path.is_empty() { key.clone() } else { format!("{field_path}.{key}") };
                let validated = validate_value(&field_value, field_schema, &new_path)?;

                if !validated.is_null()
                    || matches!(
                        field_schema,
                        SchemaType::String { optional: false, .. }
                            | SchemaType::Number { optional: false, .. }
                            | SchemaType::Boolean { optional: false, .. }
                    )
                {
                    validated_obj.insert(key.clone(), validated);
                }
            }

            Ok(Value::Object(validated_obj))
        }
        SchemaType::Literal { optional, default, value: literal_value } => {
            if value.is_null() {
                if *optional {
                    return Ok(default.clone().unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            let compare_value = if value.is_string() {
                value.clone()
            } else if literal_value.is_string() && !value.is_string() {
                Value::String(value.to_string())
            } else {
                value.clone()
            };

            if &compare_value != literal_value {
                return Err(ValidationError::new(
                    field_path,
                    format!("Value must be exactly {literal_value:?}"),
                ));
            }

            Ok(value.clone())
        }
        SchemaType::Union { optional, default, schemas } => {
            if value.is_null() {
                if *optional {
                    return Ok(default.clone().unwrap_or(Value::Null));
                }
                return Err(ValidationError::new(field_path, "Field is required"));
            }

            for schema in schemas {
                if let Ok(validated) = validate_value(value, schema, field_path) {
                    return Ok(validated);
                }
            }

            Err(ValidationError::new(field_path, "Value does not match any union type"))
        }
    }
}


================================================
FILE: packages/core/src/validation.rs
================================================
pub mod parser;
pub mod parser_tests;
pub mod tests;
pub mod types;
pub mod validators;

pub use parser::*;
pub use types::*;
pub use validators::*;


================================================
FILE: packages/core/tsconfig.json
================================================
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "dist"
  },
  "include": ["src"],
  "references": []
}


================================================
FILE: packages/kitojs/.gitignore
================================================
dist/
docs/

================================================
FILE: packages/kitojs/package.json
================================================
{
  "name": "kitojs",
  "version": "1.0.0-alpha.8",
  "description": "🐺 The high-performance, type-safe and modern TypeScript web framework written in Rust.",
  "scripts": {
    "build": "tsdown",

    "test": "vitest run",
    "test:watch": "vitest",
    "test:coverage": "vitest run --coverage",

    "docs": "typedoc",
    "docs:watch": "typedoc --watch",
    "docs:serve": "pnpm dlx serve docs"
  },

  "dependencies": {
    "@kitojs/kito-core": "workspace:*",
    "acorn": "^8.15.0",
    "acorn-walk": "^8.3.4"
  },
  "devDependencies": {
    "@kitojs/types": "workspace:*",
    "@vitest/coverage-v8": "^4.0.9",
    "tsdown": "^0.15.0",
    "typedoc": "^0.28.14",
    "vitest": "^4.0.9"
  },
  "peerDependencies": {
    "typescript": "^5.9.2"
  },

  "repository": {
    "type": "git",
    "url": "https://github.com/kitojs/kito.git"
  },
  "homepage": "https://kito.pages.dev",
  "bugs": {
    "url": "https://github.com/kitojs/kito/issues"
  },

  "license": "MIT",
  "author": {
    "name": "Nehuén",
    "url": "https://github.com/nehu3n"
  },

  "type": "module",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },

  "files": [
    "dist",
    "readme.md",
    "package.json"
  ]
}


================================================
FILE: packages/kitojs/readme.md
================================================
<div align="center">
  <img src="https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-banner.svg" width="220px" />
  
  <br />
  <br />
  
  <p>
    <strong>High-performance</strong>, fully <strong>type-safe</strong>, and modern web framework for <strong>TypeScript</strong>.  
    Powered by <strong>Rust</strong> for extreme speed and low memory usage.
  </p>
</div>

---

- **Extreme performance** – Rust core optimized for extreme speed & efficiency. **See the [benchmarks](https://github.com/kitojs/kito/tree/main/bench).**
- **Type-safe** – full TypeScript support with end-to-end safety and exceptional DX.
- **Schema validation** – built-in validation with zero bloat.  
- **Middleware system** – composable and flexible like you expect.
- **Cross-platform** – runs on Node.js, Bun, and Deno.  

---

## 🚀 Quick Start

You can add **Kito** to an existing project:

```bash
pnpm add kitojs

# Or: npm/yarn/bun add kitojs
# Or: deno add npm:kitojs
```

Or create a new project instantly with the [official starter](https://github.com/kitojs/create-kitojs):

```bash
pnpm create kitojs

# Or: npm/yarn/bun create kitojs
# Or: deno init --npm kitojs
```

### Minimal Example

```ts
import { server } from "kitojs";
const app = server();

app.get("/", ({ res }) => {
  res.send("hello world!");
});

app.listen(3000);
```

<details>
  <summary><strong>Fluent style</strong></summary>

  Kito also supports fluent style. You can chain all methods. **See the examples [here](https://github.com/kitojs/kito/tree/main/examples/fluent).**

  ```ts
  import { server } from "kitojs";

  server()
    .get("/", ({ res }) => res.send("hello world!"))
    .listen(3000);
  ```
</details>

---

## 📚 Documentation

Full docs available at the [**official website**](https://kito.pages.dev).
You can also explore ready-to-run [examples](https://github.com/kitojs/kito/tree/main/examples).

---

## 🤝 Contributing

We welcome contributions! Check the [**contributing guide**](https://github.com/kitojs/kito/blob/main/contributing.md) to learn how to set up your environment and submit pull requests.

---

## 📄 License

Licensed under the [MIT License](https://github.com/kitojs/kito/blob/main/license).

---


================================================
FILE: packages/kitojs/src/helpers/middleware.ts
================================================
import type { MiddlewareDefinition, MiddlewareHandler } from "@kitojs/types";

/**
 * Creates a typed middleware definition.
 *
 * @template TExtensions - Type of context extensions available in the middleware
 * @param handler - Middleware function that processes requests
 * @returns Middleware definition object
 *
 * @example
 * ```typescript
 * import { middleware } from 'kitojs';
 *
 * // Basic middleware
 * const logger = middleware((ctx, next) => {
 *   console.log(`${ctx.req.method} ${ctx.req.url}`);
 *   next();
 * });
 *
 * // Authentication middleware
 * const auth = middleware((ctx, next) => {
 *   const token = ctx.req.headers.authorization;
 *
 *   if (!token || !verifyToken(token)) {
 *     ctx.res.status(401).send('Unauthorized');
 *     return;
 *   }
 *
 *   next();
 * });
 *
 * // Async middleware
 * const asyncAuth = middleware(async (ctx, next) => {
 *   const user = await validateUser(ctx.req.headers.authorization);
 *   if (!user) {
 *     ctx.res.status(401).send('Unauthorized');
 *     return;
 *   }
 *   await next();
 * });
 *
 * // Using middleware
 * app.use(logger); // global
 *
 * // Route middleware
 * app.get('/protected', [auth], ctx => {
 *   ctx.res.send('Secret data');
 * });
 * ```
 */
export function middleware<TSchema = unknown, TExtensions = unknown>(
  handler: MiddlewareHandler<TSchema, TExtensions>,
): MiddlewareDefinition {
  return {
    type: "function",
    handler: handler as MiddlewareHandler,
    global: false,
  };
}


================================================
FILE: packages/kitojs/src/helpers/schema.ts
================================================
// biome-ignore assist/source/organizeImports: ...
import type {
  SchemaDefinition,
  JSONSchemaDefinition,
  InferJSONSchemaRequest,
} from "@kitojs/types";

import { convertJSONSchema } from "../schemas/jsonSchema";

/**
 * Creates a typed schema definition for request validation.
 * This is a type helper that preserves schema structure for type inference.
 *
 * @template T - Schema definition type
 * @param definition - Schema definition object
 * @returns The same schema definition with preserved types
 *
 * @example
 * ```typescript
 * import { schema, t } from 'kitojs';
 *
 * const userSchema = schema({
 *   params: t.object({
 *     id: t.str().uuid()
 *   }),
 *   query: t.object({
 *     limit: t.num().min(1).max(100).default(10)
 *   }),
 *   body: t.object({
 *     name: t.str().min(1),
 *     email: t.str().email()
 *   }),
 *   headers: t.object({
 *     authorization: t.str()
 *   })
 * });
 *
 * app.post('/users/:id', ({ req, res }) => {
 *   // All request parts are type-safe and validated
 *   const id = req.params.id; // string (UUID validated)
 *   const limit = req.query.limit; // number
 *   const name = req.body.name; // string
 * }, userSchema);
 * ```
 */
export function schema<T extends SchemaDefinition>(definition: T): T {
  return definition;
}

/**
 * Converts a JSON Schema definition to internal schema format
 * @template T - JSON Schema definition type
 * @param definition - JSON Schema definition object
 * @returns Converted schema definition with preserved types
 *
 * @example
 * ```typescript
 * import { schema } from 'kitojs';
 *
 * const userSchema = schema.json({
 *   params: {
 *     type: 'object',
 *     properties: {
 *       id: { type: 'string', format: 'uuid' }
 *     },
 *     required: ['id']
 *   },
 *   body: {
 *     type: 'object',
 *     properties: {
 *       name: { type: 'string', minLength: 1 },
 *       email: { type: 'string', format: 'email' }
 *     },
 *     required: ['name', 'email']
 *   }
 * });
 *
 * app.post('/users/:id', ({ req, res }) => {
 *   // types are inferred from JSON Schema
 *   const id = req.params.id; // string
 *   const name = req.body.name; // string
 * }, userSchema);
 * ```
 */
schema.json = <T extends JSONSchemaDefinition>(
  definition: T,
): SchemaDefinition & {
  __jsonSchemaInfer: InferJSONSchemaRequest<T>;
} => {
  // biome-ignore lint/suspicious/noExplicitAny: ...
  const converted: any = {};

  if (definition.params) {
    converted.params = convertJSONSchema(definition.params);
  }
  if (definition.query) {
    converted.query = convertJSONSchema(definition.query);
  }
  if (definition.body) {
    converted.body = convertJSONSchema(definition.body);
  }
  if (definition.headers) {
    converted.headers = convertJSONSchema(definition.headers);
  }
  if (definition.response) {
    converted.response = {};
    for (const [statusCode, responseSchema] of Object.entries(
      definition.response,
    )) {
      converted.response[statusCode] = convertJSONSchema(responseSchema);
    }
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  return converted as any;
};


================================================
FILE: packages/kitojs/src/index.ts
================================================
/**
 * @module kitojs
 *
 * Kito is a high-performance, type-safe TypeScript web framework with a Rust core.
 *
 * @example Basic usage
 * ```typescript
 * import { server } from 'kitojs';
 *
 * const app = server();
 *
 * app.get('/', ctx => {
 *   ctx.res.send('Hello World!');
 * });
 *
 * app.listen(3000);
 * ```
 *
 * @example With schema validation
 * ```typescript
 * import { server, schema, t } from 'kitojs';
 *
 * const userSchema = schema({
 *   params: t.object({ id: t.str().uuid() }),
 *   body: t.object({
 *     name: t.str().min(1),
 *     email: t.str().email()
 *   })
 * });
 *
 * app.post('/users/:id', [userSchema], ctx => {
 *   ctx.res.json({
 *     id: ctx.req.params.id,
 *     ...ctx.req.body
 *   });
 * });
 * ```
 *
 * @example With middleware
 * ```typescript
 * import { server, middleware } from 'kitojs';
 *
 * const logger = middleware((ctx, next) => {
 *   console.log(`${ctx.req.method} ${ctx.req.url}`);
 *   next();
 * });
 *
 * app.use(logger);
 * ```
 *
 * @example With context extensions
 * ```typescript
 * const app = server().extend<{ db: Database }>(ctx => {
 *   ctx.db = createDatabase();
 * });
 *
 * app.get('/users', async ctx => {
 *   const users = await ctx.db.query('SELECT * FROM users');
 *   ctx.res.json(users);
 * });
 * ```
 *
 * @example With routers
 * ```typescript
 * import { server, router } from 'kitojs';
 *
 * const apiRouter = router();
 * apiRouter.get('/users', ({ res }) => res.json({ users: [] }));
 *
 * const app = server();
 * app.mount('/api', apiRouter);
 * app.listen(3000);
 * ```
 */

// biome-ignore assist/source/organizeImports: ...
export * from "./schemas/builders";

export * from "./helpers/schema";
export * from "./helpers/middleware";

export * from "./server/server";
export * from "./server/router";
export * from "./types";


================================================
FILE: packages/kitojs/src/schemas/builders.ts
================================================
// biome-ignore assist/source/organizeImports: ...
import { StringSchemaImpl } from "./primitives/string";
import { NumberSchemaImpl } from "./primitives/number";
import { BooleanSchemaImpl } from "./primitives/boolean";
import { ArraySchemaImpl } from "./primitives/array";
import { ObjectSchemaImpl } from "./primitives/object";
import { LiteralSchemaImpl } from "./primitives/literal";
import { UnionSchemaImpl } from "./primitives/union";

import type {
  StringSchema,
  NumberSchema,
  BooleanSchema,
  ArraySchema,
  ObjectSchema,
  LiteralSchema,
  UnionSchema,
  SchemaType,
} from "@kitojs/types";

/**
 * Schema builder utilities for creating type-safe request validation schemas.
 *
 * @example
 * ```typescript
 * import { t, schema } from 'kitojs';
 *
 * const userSchema = schema({
 *   params: t.object({
 *     id: t.str().uuid()
 *   }),
 *   body: t.object({
 *     name: t.str().min(1).max(50),
 *     email: t.str().email(),
 *     age: t.num().min(0).optional()
 *   })
 * });
 *
 * app.post('/users/:id', [userSchema], ctx => {
 *   // ctx.req.params.id is validated as UUID
 *   // ctx.req.body is type-safe and validated
 * });
 * ```
 */
export const t = {
  /**
   * Creates a string schema builder.
   *
   * @returns String schema with validation methods
   *
   * @example
   * ```typescript
   * t.str() // basic string
   * t.str().min(3).max(50) // length constraints
   * t.str().email() // email validation
   * t.str().uuid() // UUID validation
   * t.str().optional() // optional field
   * t.str().default('hello') // default value
   * ```
   */
  str(): StringSchema {
    return new StringSchemaImpl();
  },

  /**
   * Creates a number schema builder.
   *
   * @returns Number schema with validation methods
   *
   * @example
   * ```typescript
   * t.num() // basic number
   * t.num().min(0).max(100) // range constraints
   * t.num().int() // integer only
   * t.num().positive() // positive numbers
   * t.num().optional() // optional field
   * t.num().default(0) // default value
   * ```
   */
  num(): NumberSchema {
    return new NumberSchemaImpl();
  },

  /**
   * Creates a boolean schema builder.
   *
   * @returns Boolean schema with validation methods
   *
   * @example
   * ```typescript
   * t.bool() // basic boolean
   * t.bool().optional() // optional field
   * t.bool().default(false) // default value
   * ```
   */
  bool(): BooleanSchema {
    return new BooleanSchemaImpl();
  },

  /**
   * Creates an array schema builder.
   *
   * @template T - Type of array items
   * @param item - Schema for array items
   * @returns Array schema with validation methods
   *
   * @example
   * ```typescript
   * t.array(t.str()) // string array
   * t.array(t.num().positive()) // array of positive numbers
   * t.array(t.object({ name: t.str() })) // array of objects
   * t.array(t.str()).min(1).max(10) // length constraints
   * ```
   */
  array<T extends SchemaType>(item: T): ArraySchema<T> {
    return new ArraySchemaImpl(item);
  },

  /**
   * Creates an object schema builder.
   *
   * @template T - Object shape definition
   * @param shape - Object property schemas
   * @returns Object schema with validation methods
   *
   * @example
   * ```typescript
   * t.object({
   *   name: t.str(),
   *   age: t.num(),
   *   email: t.str().email().optional()
   * })
   *
   * // Nested objects
   * t.object({
   *   user: t.object({
   *     profile: t.object({
   *       bio: t.str()
   *     })
   *   })
   * })
   * ```
   */
  object<T extends Record<string, SchemaType>>(shape: T): ObjectSchema<T> {
    return new ObjectSchemaImpl(shape);
  },

  /**
   * Creates a literal schema for exact value matching.
   *
   * @template T - Literal value type
   * @param value - Exact value to match
   * @returns Literal schema
   *
   * @example
   * ```typescript
   * t.literal('admin') // matches only "admin"
   * t.literal(42) // matches only 42
   * t.literal(true) // matches only true
   * ```
   */
  literal<T extends string | number | boolean>(value: T): LiteralSchema<T> {
    return new LiteralSchemaImpl(value);
  },

  /**
   * Creates a union schema for multiple possible types.
   *
   * @template T - Array of possible schema types
   * @param schemas - Schemas to union
   * @returns Union schema
   *
   * @example
   * ```typescript
   * // String or number
   * t.union(t.str(), t.num())
   *
   * // Enum-like literals
   * t.union(
   *   t.literal('admin'),
   *   t.literal('user'),
   *   t.literal('guest')
   * )
   *
   * // Complex types
   * t.union(
   *   t.object({ type: t.literal('user'), name: t.str() }),
   *   t.object({ type: t.literal('guest') })
   * )
   * ```
   */
  union<T extends SchemaType[]>(...schemas: T): UnionSchema<T> {
    return new UnionSchemaImpl(schemas);
  },
};


================================================
FILE: packages/kitojs/src/schemas/index.ts
================================================
// biome-ignore assist/source/organizeImports: ...
export * from "./builders";

export * from "./primitives/string";
export * from "./primitives/number";
export * from "./primitives/boolean";
export * from "./primitives/array";
export * from "./primitives/object";
export * from "./primitives/literal";
export * from "./primitives/union";


================================================
FILE: packages/kitojs/src/schemas/jsonSchema.ts
================================================
// biome-ignore assist/source/organizeImports: ...
import type {
  SchemaType,
  JSONSchema,
  JSONSchemaString,
  JSONSchemaNumber,
  JSONSchemaBoolean,
  JSONSchemaArray,
  JSONSchemaObject,
} from "@kitojs/types";

import { t } from "./builders";

export function convertJSONSchema(schema: JSONSchema): SchemaType {
  switch (schema.type) {
    case "string":
      return convertStringSchema(schema as JSONSchemaString);
    case "number":
    case "integer":
      return convertNumberSchema(schema as JSONSchemaNumber);
    case "boolean":
      return convertBooleanSchema(schema as JSONSchemaBoolean);
    case "array":
      return convertArraySchema(schema as JSONSchemaArray);
    case "object":
      return convertObjectSchema(schema as JSONSchemaObject);
    default:
      // biome-ignore lint/suspicious/noExplicitAny: ...
      throw new Error(`Unsupported JSON Schema type: ${(schema as any).type}`);
  }
}

function convertStringSchema(schema: JSONSchemaString): SchemaType {
  if (schema.const !== undefined) {
    let schemaBuilder = t.literal(schema.const);
    if (schema.default !== undefined) {
      // biome-ignore lint/suspicious/noExplicitAny: ...
      schemaBuilder = schemaBuilder.default(schema.default as string) as any;
    }
    return schemaBuilder as SchemaType;
  }

  if (schema.enum && schema.enum.length > 0) {
    const literals = schema.enum.map((value) => t.literal(value));
    let schemaBuilder = t.union(...literals);
    if (schema.default !== undefined) {
      schemaBuilder = schemaBuilder.default(
        schema.default as (typeof schema.enum)[number],
        // biome-ignore lint/suspicious/noExplicitAny: ...
      ) as any;
    }
    return schemaBuilder as SchemaType;
  }

  let schemaBuilder = t.str();

  if (schema.minLength !== undefined) {
    schemaBuilder = schemaBuilder.min(schema.minLength);
  }
  if (schema.maxLength !== undefined) {
    schemaBuilder = schemaBuilder.max(schema.maxLength);
  }

  if (schema.format) {
    switch (schema.format) {
      case "email":
        schemaBuilder = schemaBuilder.email();
        break;
      case "uuid":
        schemaBuilder = schemaBuilder.uuid();
        break;
      case "uri":
        schemaBuilder = schemaBuilder.url();
        break;
    }
  }

  if (schema.pattern) {
    schemaBuilder = schemaBuilder.regex(new RegExp(schema.pattern));
  }

  if (schema.default !== undefined) {
    // biome-ignore lint/suspicious/noExplicitAny: ...
    schemaBuilder = schemaBuilder.default(schema.default as string) as any;
  }

  return schemaBuilder as SchemaType;
}

function convertNumberSchema(schema: JSONSchemaNumber): SchemaType {
  if (schema.const !== undefined) {
    let schemaBuilder = t.literal(schema.const);
    if (schema.default !== undefined) {
      // biome-ignore lint/suspicious/noExplicitAny: ...
      schemaBuilder = schemaBuilder.default(schema.default as number) as any;
    }
    return schemaBuilder as SchemaType;
  }

  if (schema.enum && schema.enum.length > 0) {
    const literals = schema.enum.map((value) => t.literal(value));
    let schemaBuilder = t.union(...literals);
    if (schema.default !== undefined) {
      schemaBuilder = schemaBuilder.default(
        schema.default as (typeof schema.enum)[number],
        // biome-ignore lint/suspicious/noExplicitAny: ...
      ) as any;
    }
    return schemaBuilder as SchemaType;
  }

  let schemaBuilder = t.num();

  if (schema.type === "integer") {
    schemaBuilder = schemaBuilder.int();
  }

  if (schema.minimum !== undefined) {
    schemaBuilder = schemaBuilder.min(schema.minimum);
  }
  if (schema.maximum !== undefined) {
    schemaBuilder = schemaBuilder.max(schema.maximum);
  }

  if (schema.default !== undefined) {
    // biome-ignore lint/suspicious/noExplicitAny: ...
    schemaBuilder = schemaBuilder.default(schema.default as number) as any;
  }

  return schemaBuilder as SchemaType;
}

function convertBooleanSchema(schema: JSONSchemaBoolean): SchemaType {
  if (schema.const !== undefined) {
    let schemaBuilder = t.literal(schema.const);
    if (schema.default !== undefined) {
      // biome-ignore lint/suspicious/noExplicitAny: ...
      schemaBuilder = schemaBuilder.default(schema.default as boolean) as any;
    }
    return schemaBuilder as SchemaType;
  }

  let schemaBuilder = t.bool();

  if (schema.default !== undefined) {
    // biome-ignore lint/suspicious/noExplicitAny: ...
    schemaBuilder = schemaBuilder.default(schema.default as boolean) as any;
  }

  return schemaBuilder as SchemaType;
}

function convertArraySchema(schema: JSONSchemaArray): SchemaType {
  const itemSchema = convertJSONSchema(schema.items);

  let schemaBuilder = t.array(itemSchema);

  if (schema.minItems !== undefined) {
    schemaBuilder = schemaBuilder.min(schema.minItems);
  }
  if (schema.maxItems !== undefined) {
    schemaBuilder = schemaBuilder.max(schema.maxItems);
  }

  if (schema.default !== undefined) {
    // biome-ignore lint/suspicious/noExplicitAny: ...
    schemaBuilder = schemaBuilder.default(schema.default as any[]) as any;
  }

  return schemaBuilder as SchemaType;
}

function convertObjectSchema(schema: JSONSchemaObject): SchemaType {
  const shape: Record<string, SchemaType> = {};
  const requiredFields = new Set(schema.required || []);

  for (const [key, propSchema] of Object.entries(schema.properties)) {
    let convertedSchema = convertJSONSchema(propSchema);

    if (!requiredFields.has(key)) {
      // biome-ignore lint/suspicious/noExplicitAny: ...
      convertedSchema = (convertedSchema as any).optional();
    }

    shape[key] = convertedSchema;
  }

  let schemaBuilder = t.object(shape);

  if (schema.default !== undefined && schema.default !== null) {
    // biome-ignore lint/suspicious/noExplicitAny: ...
    schemaBuilder = schemaBuilder.default(schema.default as any) as any;
  }

  return schemaBuilder as SchemaType;
}


================================================
FILE: packages/kitojs/src/schemas/primitives/array.ts
================================================
import type { ArraySchema, SchemaType } from "@kitojs/types";

export class ArraySchemaImpl<T extends SchemaType> implements ArraySchema<T> {
  // biome-ignore lint/suspicious/noExplicitAny: ...
  _type!: any[];
  _optional = false;
  _default: unknown = undefined;
  // biome-ignore lint/suspicious/noExplicitAny: ...
  private constraints: any[] = [];

  constructor(private item: T) {}

  min(length: number): ArraySchema<T> {
    this.constraints.push({ type: "min", value: length });
    return this;
  }

  max(length: number): ArraySchema<T> {
    this.constraints.push({ type: "max", value: length });
    return this;
  }

  length(length: number): ArraySchema<T> {
    this.constraints.push({ type: "length", value: length });
    return this;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  optional(): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    return clone;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  default(value: any[]): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    clone._default = value;
    return clone;
  }

  _serialize() {
    return {
      type: "array",
      optional: this._optional,
      default: this._default,
      constraints: this.constraints,
      // biome-ignore lint/suspicious/noExplicitAny: ...
      item: (this.item as any)._serialize(),
    };
  }
}


================================================
FILE: packages/kitojs/src/schemas/primitives/boolean.ts
================================================
import type { BooleanSchema } from "@kitojs/types";

export class BooleanSchemaImpl implements BooleanSchema {
  _type!: boolean;
  _optional = false;
  _default: unknown = undefined;

  // biome-ignore lint/suspicious/noExplicitAny: ...
  optional(): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    return clone;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  default(value: boolean): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    clone._default = value;
    return clone;
  }

  _serialize() {
    return {
      type: "boolean",
      optional: this._optional,
      default: this._default,
    };
  }
}


================================================
FILE: packages/kitojs/src/schemas/primitives/literal.ts
================================================
import type { LiteralSchema } from "@kitojs/types";

export class LiteralSchemaImpl<T extends string | number | boolean>
  implements LiteralSchema<T>
{
  _type!: T;
  _optional = false;
  _default: unknown = undefined;

  constructor(private value: T) {}

  // biome-ignore lint/suspicious/noExplicitAny: ...
  optional(): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    return clone;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  default(value: T): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    clone._default = value;
    return clone;
  }

  _serialize() {
    return {
      type: "literal",
      optional: this._optional,
      default: this._default,
      value: this.value,
    };
  }
}


================================================
FILE: packages/kitojs/src/schemas/primitives/number.ts
================================================
import type { NumberSchema } from "@kitojs/types";

export class NumberSchemaImpl implements NumberSchema {
  _type!: number;
  _optional = false;
  _default: unknown = undefined;
  // biome-ignore lint/suspicious/noExplicitAny: ...
  private constraints: any[] = [];

  min(value: number): NumberSchema {
    this.constraints.push({ type: "min", value });
    return this;
  }

  max(value: number): NumberSchema {
    this.constraints.push({ type: "max", value });
    return this;
  }

  int(): NumberSchema {
    this.constraints.push({ type: "int" });
    return this;
  }

  positive(): NumberSchema {
    this.constraints.push({ type: "positive" });
    return this;
  }

  negative(): NumberSchema {
    this.constraints.push({ type: "negative" });
    return this;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  optional(): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    return clone;
  }

  // biome-ignore lint/suspicious/noExplicitAny: ...
  default(value: number): any {
    const clone = Object.assign(
      Object.create(Object.getPrototypeOf(this)),
      this,
    );
    clone._optional = true;
    clone._default = value;
    return clone;
  }

  _serialize() {
    return {
      type: "number",
      optional: this._optional,
      default: this._default,
      constraints: this.constraints,
    };
  }
}


================================================
FILE: p
Download .txt
gitextract_l4urthhv/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   └── workflows/
│       ├── ci.yml
│       ├── doc-deploy.yml
│       └── release.yml
├── .gitignore
├── Cargo.toml
├── bench/
│   ├── cases/
│   │   └── basic/
│   │       ├── elysia.ts
│   │       ├── express.ts
│   │       ├── fastify.ts
│   │       ├── hapi.ts
│   │       ├── hono.ts
│   │       ├── kito.ts
│   │       ├── koa.ts
│   │       ├── restify.ts
│   │       └── tinyhttp.ts
│   ├── config.ts
│   ├── package.json
│   ├── readme.md
│   ├── results/
│   │   ├── comparison-bun.json
│   │   ├── comparison-node.json
│   │   └── data/
│   │       ├── bun/
│   │       │   ├── elysia.json
│   │       │   ├── express.json
│   │       │   ├── fastify.json
│   │       │   ├── hapi.json
│   │       │   ├── hono.json
│   │       │   ├── kito.json
│   │       │   ├── koa.json
│   │       │   └── tinyhttp.json
│   │       └── node/
│   │           ├── elysia.json
│   │           ├── express.json
│   │           ├── fastify.json
│   │           ├── hapi.json
│   │           ├── hono.json
│   │           ├── kito.json
│   │           ├── koa.json
│   │           ├── restify.json
│   │           └── tinyhttp.json
│   ├── runBench.ts
│   ├── tsconfig.json
│   └── utils/
│       ├── chart.ts
│       ├── frameworkRunner.ts
│       ├── http.ts
│       └── wait.ts
├── biome.json
├── cli/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── install.js
│   ├── package.json
│   └── src/
│       ├── commands.rs
│       ├── main.rs
│       └── utils.rs
├── cliff.toml
├── examples/
│   ├── fluent/
│   │   ├── basic.ts
│   │   ├── clustering/
│   │   │   ├── index.ts
│   │   │   └── server.ts
│   │   ├── extend.ts
│   │   ├── file.ts
│   │   ├── middlewares/
│   │   │   ├── index.ts
│   │   │   └── samples/
│   │   │       ├── auth.ts
│   │   │       └── logger.ts
│   │   ├── params.ts
│   │   ├── route.ts
│   │   ├── router/
│   │   │   ├── cats.ts
│   │   │   └── index.ts
│   │   ├── schemas/
│   │   │   ├── builder.ts
│   │   │   └── json.ts
│   │   ├── streaming/
│   │   │   ├── sse.ts
│   │   │   └── stream.ts
│   │   └── unixSocket.ts
│   ├── instance/
│   │   ├── basic.ts
│   │   ├── clustering/
│   │   │   ├── index.ts
│   │   │   └── server.ts
│   │   ├── extend.ts
│   │   ├── file.ts
│   │   ├── middlewares/
│   │   │   ├── index.ts
│   │   │   └── samples/
│   │   │       ├── auth.ts
│   │   │       └── logger.ts
│   │   ├── params.ts
│   │   ├── route.ts
│   │   ├── router/
│   │   │   ├── cats.ts
│   │   │   └── index.ts
│   │   ├── schemas/
│   │   │   ├── builder.ts
│   │   │   └── json.ts
│   │   ├── streaming/
│   │   │   ├── sse.ts
│   │   │   └── stream.ts
│   │   └── unixSocket.ts
│   ├── package.json
│   ├── runExample.ts
│   └── tsconfig.json
├── lefthook.yml
├── license
├── package.json
├── packages/
│   ├── core/
│   │   ├── .gitignore
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── http/
│   │   │   │   ├── cookies.rs
│   │   │   │   ├── cookies_tests.rs
│   │   │   │   ├── files.rs
│   │   │   │   ├── mime.rs
│   │   │   │   ├── mime_tests.rs
│   │   │   │   ├── request.rs
│   │   │   │   └── response.rs
│   │   │   ├── http.rs
│   │   │   ├── lib.rs
│   │   │   ├── server/
│   │   │   │   ├── context.rs
│   │   │   │   ├── core.rs
│   │   │   │   ├── handler.rs
│   │   │   │   ├── router.rs
│   │   │   │   └── routes.rs
│   │   │   ├── server.rs
│   │   │   ├── validation/
│   │   │   │   ├── parser.rs
│   │   │   │   ├── parser_tests.rs
│   │   │   │   ├── tests.rs
│   │   │   │   ├── types.rs
│   │   │   │   └── validators.rs
│   │   │   └── validation.rs
│   │   └── tsconfig.json
│   ├── kitojs/
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── readme.md
│   │   ├── src/
│   │   │   ├── helpers/
│   │   │   │   ├── middleware.ts
│   │   │   │   └── schema.ts
│   │   │   ├── index.ts
│   │   │   ├── schemas/
│   │   │   │   ├── builders.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── jsonSchema.ts
│   │   │   │   └── primitives/
│   │   │   │       ├── array.ts
│   │   │   │       ├── boolean.ts
│   │   │   │       ├── literal.ts
│   │   │   │       ├── number.ts
│   │   │   │       ├── object.ts
│   │   │   │       ├── string.ts
│   │   │   │       └── union.ts
│   │   │   ├── server/
│   │   │   │   ├── analyzer.ts
│   │   │   │   ├── request.ts
│   │   │   │   ├── response.ts
│   │   │   │   ├── router.ts
│   │   │   │   └── server.ts
│   │   │   └── types.ts
│   │   ├── tests/
│   │   │   ├── analyzer.test.ts
│   │   │   ├── middleware.test.ts
│   │   │   ├── route-chain.test.ts
│   │   │   ├── router.test.ts
│   │   │   ├── schema-helper.test.ts
│   │   │   ├── server.test.ts
│   │   │   └── types.test.ts
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   ├── typedoc.json
│   │   └── vitest.config.ts
│   ├── readme.md
│   └── types/
│       ├── .gitignore
│       ├── package.json
│       ├── src/
│       │   ├── context.d.ts
│       │   ├── handlers.d.ts
│       │   ├── http/
│       │   │   ├── request.d.ts
│       │   │   └── response.d.ts
│       │   ├── index.d.ts
│       │   ├── router.d.ts
│       │   ├── routes.d.ts
│       │   ├── schema/
│       │   │   ├── array.d.ts
│       │   │   ├── base.d.ts
│       │   │   ├── boolean.d.ts
│       │   │   ├── jsonSchema.d.ts
│       │   │   ├── literal.d.ts
│       │   │   ├── number.d.ts
│       │   │   ├── object.d.ts
│       │   │   ├── string.d.ts
│       │   │   └── union.d.ts
│       │   └── server.d.ts
│       ├── tsconfig.json
│       └── tsdown.config.ts
├── pnpm-workspace.yaml
├── readme.md
├── rust-toolchain.toml
├── rustfmt.toml
└── tsconfig.base.json
Download .txt
SYMBOL INDEX (408 symbols across 71 files)

FILE: bench/cases/basic/elysia.ts
  function start (line 6) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/express.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/fastify.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/hapi.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/hono.ts
  function start (line 6) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/kito.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/koa.ts
  function start (line 4) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/restify.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/cases/basic/tinyhttp.ts
  function start (line 3) | function start(port: number): { stop: () => void } {

FILE: bench/config.ts
  type FrameworkConfig (line 1) | type FrameworkConfig = string;
  type FrameworkRuntime (line 3) | type FrameworkRuntime = "bun" | "node";

FILE: bench/runBench.ts
  type BenchmarkResult (line 15) | type BenchmarkResult = {
  type RunningBenchmark (line 24) | type RunningBenchmark = {
  type NormalizedFramework (line 28) | type NormalizedFramework = {
  constant CURRENT_RUNTIME (line 33) | const CURRENT_RUNTIME: FrameworkRuntime =
  constant PROJECT_ROOT (line 36) | const PROJECT_ROOT = path.dirname(fileURLToPath(import.meta.url));
  constant RUNNER_ENTRY (line 37) | const RUNNER_ENTRY = path.join(PROJECT_ROOT, "utils", "frameworkRunner.t...
  constant PNPM_BIN (line 38) | const PNPM_BIN = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
  function launchFramework (line 40) | async function launchFramework(
  function spawnFrameworkProcess (line 71) | function spawnFrameworkProcess(
  function stopChildProcess (line 98) | async function stopChildProcess(child: ChildProcess): Promise<void> {
  function getMachineSpecs (line 117) | function getMachineSpecs() {
  function main (line 125) | async function main() {

FILE: bench/utils/chart.ts
  type ChartData (line 24) | type ChartData = {
  function generateChart (line 31) | async function generateChart(

FILE: bench/utils/frameworkRunner.ts
  function shutdown (line 20) | async function shutdown(code = 0) {

FILE: bench/utils/http.ts
  type WrkResult (line 6) | type WrkResult = {

FILE: bench/utils/wait.ts
  function waitForServerReady (line 3) | function waitForServerReady(port: number, retries = 50): Promise<void> {

FILE: cli/src/commands.rs
  type Command (line 6) | pub(crate) trait Command {
    method run (line 7) | async fn run(&self) -> Result<(), ()>;

FILE: cli/src/main.rs
  type Cli (line 16) | struct Cli {
  type Commands (line 22) | enum Commands {}
  method run (line 26) | async fn run(&self) -> Result<(), ()> {
  function main (line 34) | async fn main() {

FILE: examples/fluent/extend.ts
  type Extends (line 3) | interface Extends {

FILE: examples/instance/extend.ts
  type Extends (line 3) | interface Extends {

FILE: packages/core/build.rs
  function main (line 1) | fn main() {

FILE: packages/core/src/http/cookies.rs
  type CookieOptionsCore (line 3) | pub struct CookieOptionsCore {
  function serialize_cookie (line 13) | pub fn serialize_cookie(name: &str, value: &str, options: &CookieOptions...

FILE: packages/core/src/http/cookies_tests.rs
  function test_basic_cookie (line 6) | fn test_basic_cookie() {
  function test_cookie_with_max_age (line 23) | fn test_cookie_with_max_age() {
  function test_cookie_with_custom_path (line 39) | fn test_cookie_with_custom_path() {
  function test_cookie_with_domain (line 55) | fn test_cookie_with_domain() {
  function test_cookie_http_only (line 71) | fn test_cookie_http_only() {
  function test_cookie_secure (line 87) | fn test_cookie_secure() {
  function test_cookie_same_site (line 103) | fn test_cookie_same_site() {
  function test_cookie_all_options (line 119) | fn test_cookie_all_options() {

FILE: packages/core/src/http/files.rs
  function read_file_for_response (line 9) | pub async fn read_file_for_response(

FILE: packages/core/src/http/mime.rs
  function get_mime_type (line 3) | pub fn get_mime_type(path: &str) -> &'static str {

FILE: packages/core/src/http/mime_tests.rs
  function test_html_mime_types (line 6) | fn test_html_mime_types() {
  function test_css_mime_type (line 12) | fn test_css_mime_type() {
  function test_javascript_mime_types (line 17) | fn test_javascript_mime_types() {
  function test_json_mime_type (line 23) | fn test_json_mime_type() {
  function test_image_mime_types (line 28) | fn test_image_mime_types() {
  function test_font_mime_types (line 38) | fn test_font_mime_types() {
  function test_video_mime_types (line 46) | fn test_video_mime_types() {
  function test_audio_mime_types (line 52) | fn test_audio_mime_types() {
  function test_default_mime_type (line 58) | fn test_default_mime_type() {
  function test_case_insensitive (line 64) | fn test_case_insensitive() {
  function test_path_with_directories (line 71) | fn test_path_with_directories() {

FILE: packages/core/src/http/request.rs
  type RequestCore (line 12) | pub struct RequestCore {
    method new (line 33) | pub async fn new(
  function get_body_buffer (line 133) | pub fn get_body_buffer(core: &External<Arc<RequestCore>>) -> Buffer {
  function get_header (line 138) | pub fn get_header(core: &External<Arc<RequestCore>>, name: String) -> Op...
  function get_all_headers (line 143) | pub fn get_all_headers(core: &External<Arc<RequestCore>>) -> HashMap<Str...
  function get_query_param (line 148) | pub fn get_query_param(core: &External<Arc<RequestCore>>, name: String) ...
  function get_all_query (line 153) | pub fn get_all_query(core: &External<Arc<RequestCore>>) -> HashMap<Strin...
  function get_param (line 158) | pub fn get_param(core: &External<Arc<RequestCore>>, name: String) -> Opt...
  function get_all_params (line 163) | pub fn get_all_params(core: &External<Arc<RequestCore>>) -> HashMap<Stri...
  function get_cookie (line 168) | pub fn get_cookie(core: &External<Arc<RequestCore>>, name: String) -> Op...
  function get_all_cookies (line 173) | pub fn get_all_cookies(core: &External<Arc<RequestCore>>) -> HashMap<Str...
  function get_method (line 178) | pub fn get_method(core: &External<Arc<RequestCore>>) -> String {
  function get_url (line 183) | pub fn get_url(core: &External<Arc<RequestCore>>) -> String {
  function get_pathname (line 188) | pub fn get_pathname(core: &External<Arc<RequestCore>>) -> String {
  function get_search (line 193) | pub fn get_search(core: &External<Arc<RequestCore>>) -> Option<String> {
  function get_protocol (line 198) | pub fn get_protocol(core: &External<Arc<RequestCore>>) -> String {
  function get_hostname (line 203) | pub fn get_hostname(core: &External<Arc<RequestCore>>) -> String {
  function get_ip (line 208) | pub fn get_ip(core: &External<Arc<RequestCore>>) -> String {
  function get_ips (line 213) | pub fn get_ips(core: &External<Arc<RequestCore>>) -> Vec<String> {
  function get_secure (line 218) | pub fn get_secure(core: &External<Arc<RequestCore>>) -> bool {
  function get_xhr (line 223) | pub fn get_xhr(core: &External<Arc<RequestCore>>) -> bool {

FILE: packages/core/src/http/response.rs
  type ResponseChannel (line 12) | pub struct ResponseChannel {
    method new (line 17) | pub fn new(tx: UnboundedSender<ResponseMessage>) -> Self {
  type ResponseMessage (line 22) | pub enum ResponseMessage {
  type ResponseBody (line 29) | pub enum ResponseBody {
  type BoxedBody (line 34) | pub type BoxedBody = BoxBody<Bytes, Box<dyn std::error::Error + Send + S...
  function send_response (line 38) | pub fn send_response(channel: &External<Arc<ResponseChannel>>, buffer: B...
  function start_stream (line 76) | pub fn start_stream(channel: &External<Arc<ResponseChannel>>, buffer: Bu...
  function send_chunk (line 104) | pub fn send_chunk(channel: &External<Arc<ResponseChannel>>, data: Buffer...
  function end_stream (line 116) | pub fn end_stream(channel: &External<Arc<ResponseChannel>>) -> napi::Res...
  type SendFileOptionsCore (line 128) | pub struct SendFileOptionsCore {

FILE: packages/core/src/server/context.rs
  type ContextObject (line 9) | pub struct ContextObject {
  method to_napi_value (line 15) | unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> napi::Result<s...

FILE: packages/core/src/server/core.rs
  type ServerOptionsCore (line 23) | pub struct ServerOptionsCore {
  type ServerCore (line 34) | pub struct ServerCore {
    method new (line 42) | pub fn new(config: ServerOptionsCore) -> Self {
    method get_config (line 47) | pub fn get_config(&self) -> ServerOptionsCore {
    method set_config (line 52) | pub fn set_config(&mut self, config: ServerOptionsCore) {
    method add_route (line 57) | pub fn add_route(&mut self, route: Route) -> napi::Result<()> {
    method start (line 72) | pub async unsafe fn start(&mut self, ready: Option<ThreadsafeFunction<...
    method start_tcp (line 85) | async fn start_tcp(
    method start_unix_socket (line 123) | async fn start_unix_socket(
    method close (line 168) | pub fn close(&self) {
  function create_reusable_listener (line 175) | async fn create_reusable_listener(addr: SocketAddr) -> std::io::Result<T...

FILE: packages/core/src/server/handler.rs
  function handle_request (line 28) | pub async fn handle_request(

FILE: packages/core/src/server/router.rs
  type TrieRouter (line 8) | pub struct TrieRouter {
    method new (line 19) | pub fn new() -> Self {
    method insert (line 23) | pub fn insert(&mut self, path: &str, route: Arc<CompiledRoute>) -> Res...
    method find (line 27) | pub fn find<'a>(&'a self, path: &'a str) -> Option<Match<'a, 'a, &'a A...
  method default (line 13) | fn default() -> Self {
  type HttpRouter (line 32) | pub struct HttpRouter {
    method new (line 44) | pub fn new() -> Self {
    method insert (line 48) | pub fn insert(&mut self, route: CompiledRoute) -> Result<(), String> {
    method find (line 60) | pub fn find<'a>(&'a self, path: &'a str) -> Option<RouteMatch> {
    method is_static_route (line 78) | fn is_static_route(path: &str) -> bool {
  method default (line 38) | fn default() -> Self {
  type RouteMatch (line 83) | pub struct RouteMatch {
  type GlobalRouter (line 88) | pub struct GlobalRouter {
    method new (line 99) | pub fn new() -> Self {
    method insert (line 103) | pub fn insert(&self, method: &str, route: CompiledRoute) -> Result<(),...
    method find (line 110) | pub fn find(&self, method: &str, path: &str) -> Option<RouteMatch> {
    method route_count (line 120) | pub fn route_count(&self) -> usize {
  method default (line 93) | fn default() -> Self {

FILE: packages/core/src/server/routes.rs
  type RouteHandler (line 21) | pub type RouteHandler = ThreadsafeFunction<ContextObject, (), ContextObj...
  type CompiledRoute (line 23) | pub struct CompiledRoute {
  type RouteSchema (line 32) | pub struct RouteSchema {
  type Route (line 42) | pub struct Route {
  type ResponseStrategy (line 53) | pub enum ResponseStrategy {
  function convert_path_to_matchit_format (line 59) | fn convert_path_to_matchit_format(path: &str) -> String {
  function insert_route (line 79) | pub fn insert_route(route: Route) -> napi::Result<()> {

FILE: packages/core/src/validation/parser.rs
  function parse_params (line 8) | pub fn parse_params(
  function parse_query (line 20) | pub fn parse_query(
  function parse_body (line 39) | pub fn parse_body(body: &[u8], schema: &SchemaType) -> Result<Value, Val...
  function parse_headers (line 53) | pub fn parse_headers(

FILE: packages/core/src/validation/parser_tests.rs
  function test_parse_params_basic (line 9) | fn test_parse_params_basic() {
  function test_parse_query_single_value (line 31) | fn test_parse_query_single_value() {
  function test_parse_query_multiple_values (line 48) | fn test_parse_query_multiple_values() {
  function test_parse_body_valid_json (line 74) | fn test_parse_body_valid_json() {
  function test_parse_body_invalid_json (line 94) | fn test_parse_body_invalid_json() {
  function test_parse_body_empty_with_optional (line 104) | fn test_parse_body_empty_with_optional() {
  function test_parse_body_empty_required (line 115) | fn test_parse_body_empty_required() {
  function test_parse_headers (line 125) | fn test_parse_headers() {
  function test_parse_params_with_validation (line 143) | fn test_parse_params_with_validation() {
  function test_parse_params_validation_fails (line 164) | fn test_parse_params_validation_fails() {

FILE: packages/core/src/validation/tests.rs
  function test_string_min_length (line 8) | fn test_string_min_length() {
  function test_string_max_length (line 16) | fn test_string_max_length() {
  function test_string_email (line 24) | fn test_string_email() {
  function test_string_uuid (line 33) | fn test_string_uuid() {
  function test_number_min (line 41) | fn test_number_min() {
  function test_number_max (line 49) | fn test_number_max() {
  function test_number_int (line 57) | fn test_number_int() {
  function test_number_positive (line 65) | fn test_number_positive() {
  function test_validate_string_value (line 74) | fn test_validate_string_value() {
  function test_validate_optional_with_default (line 87) | fn test_validate_optional_with_default() {
  function test_validate_number_from_string (line 99) | fn test_validate_number_from_string() {
  function test_validate_boolean_from_string (line 107) | fn test_validate_boolean_from_string() {
  function test_validate_array (line 117) | fn test_validate_array() {
  function test_validate_object (line 133) | fn test_validate_object() {
  function test_validate_literal (line 165) | fn test_validate_literal() {
  function test_validate_union (line 173) | fn test_validate_union() {

FILE: packages/core/src/validation/types.rs
  type SchemaType (line 8) | pub enum SchemaType {
  type StringConstraint (line 48) | pub enum StringConstraint {
  type NumberConstraint (line 60) | pub enum NumberConstraint {
  type ArrayConstraint (line 70) | pub enum ArrayConstraint {
  type ValidationError (line 77) | pub struct ValidationError {
    method new (line 83) | pub fn new(field: impl Into<String>, message: impl Into<String>) -> Se...

FILE: packages/core/src/validation/validators.rs
  function validate_string (line 6) | pub fn validate_string(
  function validate_number (line 70) | pub fn validate_number(
  function validate_value (line 106) | pub fn validate_value(

FILE: packages/kitojs/src/helpers/middleware.ts
  function middleware (line 51) | function middleware<TSchema = unknown, TExtensions = unknown>(

FILE: packages/kitojs/src/helpers/schema.ts
  function schema (line 46) | function schema<T extends SchemaDefinition>(definition: T): T {

FILE: packages/kitojs/src/schemas/builders.ts
  method str (line 61) | str(): StringSchema {
  method num (line 80) | num(): NumberSchema {
  method bool (line 96) | bool(): BooleanSchema {
  method array (line 115) | array<T extends SchemaType>(item: T): ArraySchema<T> {
  method object (line 144) | object<T extends Record<string, SchemaType>>(shape: T): ObjectSchema<T> {
  method literal (line 162) | literal<T extends string | number | boolean>(value: T): LiteralSchema<T> {
  method union (line 192) | union<T extends SchemaType[]>(...schemas: T): UnionSchema<T> {

FILE: packages/kitojs/src/schemas/jsonSchema.ts
  function convertJSONSchema (line 14) | function convertJSONSchema(schema: JSONSchema): SchemaType {
  function convertStringSchema (line 33) | function convertStringSchema(schema: JSONSchemaString): SchemaType {
  function convertNumberSchema (line 90) | function convertNumberSchema(schema: JSONSchemaNumber): SchemaType {
  function convertBooleanSchema (line 133) | function convertBooleanSchema(schema: JSONSchemaBoolean): SchemaType {
  function convertArraySchema (line 153) | function convertArraySchema(schema: JSONSchemaArray): SchemaType {
  function convertObjectSchema (line 173) | function convertObjectSchema(schema: JSONSchemaObject): SchemaType {

FILE: packages/kitojs/src/schemas/primitives/array.ts
  class ArraySchemaImpl (line 3) | class ArraySchemaImpl<T extends SchemaType> implements ArraySchema<T> {
    method constructor (line 11) | constructor(private item: T) {}
    method min (line 13) | min(length: number): ArraySchema<T> {
    method max (line 18) | max(length: number): ArraySchema<T> {
    method length (line 23) | length(length: number): ArraySchema<T> {
    method optional (line 29) | optional(): any {
    method default (line 39) | default(value: any[]): any {
    method _serialize (line 49) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/boolean.ts
  class BooleanSchemaImpl (line 3) | class BooleanSchemaImpl implements BooleanSchema {
    method optional (line 9) | optional(): any {
    method default (line 19) | default(value: boolean): any {
    method _serialize (line 29) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/literal.ts
  class LiteralSchemaImpl (line 3) | class LiteralSchemaImpl<T extends string | number | boolean>
    method constructor (line 10) | constructor(private value: T) {}
    method optional (line 13) | optional(): any {
    method default (line 23) | default(value: T): any {
    method _serialize (line 33) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/number.ts
  class NumberSchemaImpl (line 3) | class NumberSchemaImpl implements NumberSchema {
    method min (line 10) | min(value: number): NumberSchema {
    method max (line 15) | max(value: number): NumberSchema {
    method int (line 20) | int(): NumberSchema {
    method positive (line 25) | positive(): NumberSchema {
    method negative (line 30) | negative(): NumberSchema {
    method optional (line 36) | optional(): any {
    method default (line 46) | default(value: number): any {
    method _serialize (line 56) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/object.ts
  class ObjectSchemaImpl (line 3) | class ObjectSchemaImpl<T extends Record<string, SchemaType>>
    method constructor (line 11) | constructor(shape: T) {
    method optional (line 16) | optional(): any {
    method default (line 26) | default(value: any): any {
    method _serialize (line 36) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/string.ts
  class StringSchemaImpl (line 3) | class StringSchemaImpl implements StringSchema {
    method min (line 10) | min(length: number): StringSchema {
    method max (line 15) | max(length: number): StringSchema {
    method length (line 20) | length(length: number): StringSchema {
    method email (line 25) | email(): StringSchema {
    method url (line 30) | url(): StringSchema {
    method uuid (line 35) | uuid(): StringSchema {
    method regex (line 40) | regex(pattern: RegExp): StringSchema {
    method optional (line 46) | optional(): any {
    method default (line 56) | default(value: string): any {
    method _serialize (line 66) | _serialize() {

FILE: packages/kitojs/src/schemas/primitives/union.ts
  class UnionSchemaImpl (line 3) | class UnionSchemaImpl<T extends SchemaType[]> implements UnionSchema<T> {
    method constructor (line 9) | constructor(private schemas: T) {}
    method optional (line 12) | optional(): any {
    method default (line 22) | default(value: any): any {
    method _serialize (line 32) | _serialize() {

FILE: packages/kitojs/src/server/analyzer.ts
  type StaticResponseType (line 4) | type StaticResponseType =
  type ResponseCall (line 22) | interface ResponseCall {
  function analyzeHandler (line 28) | function analyzeHandler(handler: Function): StaticResponseType {
  function evaluateStaticValue (line 172) | function evaluateStaticValue(node: any, source: string): any {
  function serializeResponseValue (line 214) | function serializeResponseValue(
  function extractTemplate (line 243) | function extractTemplate(node: any): string {

FILE: packages/kitojs/src/server/request.ts
  class RequestBuilder (line 29) | class RequestBuilder implements KitoRequest {
    method constructor (line 51) | constructor(requestCore: any) {
    method body (line 56) | get body(): any {
    method json (line 75) | json<T = unknown>(): T {
    method text (line 91) | text(): string {
    method headers (line 99) | get headers(): RequestHeaders {
    method header (line 108) | header(name: string): string | undefined {
    method query (line 113) | get query(): Record<string, string | string[]> {
    method queryParam (line 120) | queryParam(name: string): string | string[] | undefined {
    method params (line 126) | get params(): Record<string, string> {
    method param (line 133) | param(name: string): string | undefined {
    method cookies (line 137) | get cookies(): Record<string, string> {
    method cookie (line 144) | cookie(name: string): string | undefined {
    method method (line 148) | get method(): string {
    method url (line 155) | get url(): string {
    method pathname (line 162) | get pathname(): string {
    method search (line 169) | get search(): string | null {
    method protocol (line 176) | get protocol(): string {
    method hostname (line 183) | get hostname(): string {
    method ip (line 190) | get ip(): string {
    method ips (line 197) | get ips(): string[] {
    method secure (line 204) | get secure(): boolean {
    method xhr (line 211) | get xhr(): boolean {
    method originalUrl (line 218) | get originalUrl(): string {
    method raw (line 222) | get raw(): {

FILE: packages/kitojs/src/server/response.ts
  constant HTTP_STATUS_MESSAGES (line 19) | const HTTP_STATUS_MESSAGES: Record<number, string> = {
  type ResponseState (line 39) | interface ResponseState {
  class StreamWriterImpl (line 46) | class StreamWriterImpl implements StreamWriter {
    method constructor (line 48) | constructor(private channel: any) {}
    method write (line 50) | write(data: string | Buffer): void {
    method end (line 55) | end(data?: string | Buffer): void {
  class SSEWriterImpl (line 64) | class SSEWriterImpl implements SSEWriter {
    method constructor (line 66) | constructor(private channel: any) {}
    method send (line 68) | send(data: unknown, event?: string, id?: string, retry?: number): void {
    method comment (line 95) | comment(text: string): void {
    method close (line 100) | close(): void {
  class ResponseBuilder (line 105) | class ResponseBuilder implements KitoResponse {
    method constructor (line 112) | constructor(responseChannel: any) {
    method checkFinished (line 121) | private checkFinished(): void {
    method serializeAndSend (line 127) | private serializeAndSend(): void {
    method startStreamingResponse (line 156) | private startStreamingResponse(): void {
    method status (line 179) | status(code: number): KitoResponse {
    method sendStatus (line 185) | sendStatus(code: number): void {
    method header (line 195) | header(name: string, value: string): KitoResponse {
    method headers (line 204) | headers(headers: Record<string, string>): KitoResponse {
    method append (line 215) | append(field: string, value: string): KitoResponse {
    method set (line 232) | set(field: string, value: string): KitoResponse {
    method get (line 238) | get(field: string): string | undefined {
    method type (line 242) | type(contentType: string): KitoResponse {
    method contentType (line 269) | contentType(contentType: string): KitoResponse {
    method cookie (line 273) | cookie(name: string, value: string, options?: CookieOptions): KitoResp...
    method serializeCookie (line 288) | private serializeCookie(
    method clearCookie (line 330) | clearCookie(name: string, options?: CookieOptions): KitoResponse {
    method end (line 339) | end(): void {
    method send (line 344) | send(data: unknown): void {
    method json (line 357) | json(data: unknown): void {
    method text (line 366) | text(data: string): void {
    method html (line 374) | html(data: string): void {
    method redirect (line 382) | redirect(url: string, code?: number): void {
    method location (line 390) | location(url: string): KitoResponse {
    method attachment (line 396) | attachment(filename?: string): KitoResponse {
    method download (line 410) | download(path: string, filename?: string, options?: SendFileOptions): ...
    method sendFile (line 417) | sendFile(path: string, options: SendFileOptions = {}): void {
    method getMimeType (line 465) | private getMimeType(path: string): string {
    method vary (line 500) | vary(field: string): KitoResponse {
    method links (line 506) | links(links: Record<string, string>): KitoResponse {
    method format (line 516) | format(obj: Record<string, () => void>): KitoResponse {
    method stream (line 536) | stream(): StreamWriter {
    method sse (line 548) | sse(): SSEWriter {

FILE: packages/kitojs/src/server/router.ts
  class KitoRouter (line 31) | class KitoRouter<TExtensions = {}>
    method use (line 52) | use(middleware: MiddlewareDefinition | MiddlewareHandler): this {
    method mount (line 82) | mount(path: string, router: KitoRouter<TExtensions>): this {
    method get (line 130) | get<TSchema extends SchemaDefinition = {}>(
    method post (line 181) | post<TSchema extends SchemaDefinition = {}>(
    method put (line 232) | put<TSchema extends SchemaDefinition = {}>(
    method delete (line 283) | delete<TSchema extends SchemaDefinition = {}>(
    method patch (line 334) | patch<TSchema extends SchemaDefinition = {}>(
    method head (line 385) | head<TSchema extends SchemaDefinition = {}>(
    method options (line 436) | options<TSchema extends SchemaDefinition = {}>(
    method route (line 482) | route(
    method addRoute (line 710) | protected addRoute<TSchema extends SchemaDefinition = {}>(
    method isSchemaDefinition (line 756) | protected isSchemaDefinition(item: any): item is SchemaDefinition {
    method getRoutes (line 760) | protected getRoutes(): RouteDefinition<TExtensions>[] {
    method getMiddlewares (line 764) | protected getMiddlewares(): MiddlewareDefinition[] {
    method normalizePath (line 768) | private normalizePath(path: string): string {
  function router (line 797) | function router<TExtensions = {}>(): KitoRouter<TExtensions> {

FILE: packages/kitojs/src/server/server.ts
  class KitoServer (line 37) | class KitoServer<TExtensions = {}>
    method constructor (line 57) | constructor(options?: ServerOptions) {
    method extend (line 94) | extend<TNewExtensions = unknown>(
    method addRoute (line 126) | protected override addRoute<TSchema extends SchemaDefinition = {}>(
    method mount (line 142) | override mount(path: string, router: KitoRouter<TExtensions>): this {
    method registerRouteWithCore (line 153) | private registerRouteWithCore(
    method serializeSchema (line 227) | private serializeSchema(schema: SchemaDefinition): string {
    method registerCatchAllRoute (line 251) | private registerCatchAllRoute(): void {
    method fuseMiddlewares (line 312) | private fuseMiddlewares<TSchema extends SchemaDefinition>(
    method listen (line 386) | async listen(
    method close (line 448) | close(): void {
  function server (line 473) | function server(options?: ServerOptions): KitoServer<{}> {

FILE: packages/kitojs/tests/analyzer.test.ts
  function fetchUser (line 141) | function fetchUser(id: string) {

FILE: packages/kitojs/tests/types.test.ts
  type UserContext (line 21) | type UserContext = Context<typeof userSchema>;
  type OptionalContext (line 46) | type OptionalContext = Context<typeof optionalSchema>;
  type ArrayContext (line 62) | type ArrayContext = Context<typeof arraySchema>;
  type NestedContext (line 83) | type NestedContext = Context<typeof nestedSchema>;
  type LiteralContext (line 108) | type LiteralContext = Context<typeof literalSchema>;
  type Database (line 117) | interface Database {
  type DB (line 133) | interface DB {
  type Cache (line 136) | interface Cache {

FILE: packages/types/src/context.d.ts
  type KitoContext (line 8) | interface KitoContext<TSchema extends SchemaDefinition = {}> {
  type Context (line 14) | type Context<TSchema extends SchemaDefinition = {}> =

FILE: packages/types/src/handlers.d.ts
  type NextFunction (line 3) | type NextFunction = () => void | Promise<void>;
  type MiddlewareHandler (line 5) | type MiddlewareHandler<TSchema = unknown, TExtensions = unknown> = (
  type RouteHandler (line 10) | type RouteHandler<TSchema extends SchemaDefinition, TExtensions> = (

FILE: packages/types/src/http/request.d.ts
  type CommonHeaderNames (line 1) | type CommonHeaderNames =
  type RequestHeaders (line 19) | interface RequestHeaders
  type ParsedUrl (line 39) | interface ParsedUrl {
  type KitoRequest (line 45) | interface KitoRequest {

FILE: packages/types/src/http/response.d.ts
  type CommonResponseHeaderNames (line 3) | type CommonResponseHeaderNames =
  type StreamWriter (line 22) | interface StreamWriter {
  type SSEWriter (line 29) | interface SSEWriter {
  type KitoResponse (line 35) | interface KitoResponse<TResponseSchema = unknown> {
  type CookieOptions (line 108) | interface CookieOptions {
  type SendFileOptions (line 119) | interface SendFileOptions {

FILE: packages/types/src/router.d.ts
  type KitoRouterInstance (line 6) | interface KitoRouterInstance<TExtensions = {}> {

FILE: packages/types/src/routes.d.ts
  type HttpMethod (line 5) | type HttpMethod =
  type RouteDefinition (line 15) | interface RouteDefinition<TExtensions = unknown> {
  type MiddlewareDefinition (line 22) | interface MiddlewareDefinition {
  type RouteChain (line 30) | type RouteChain<TExtensions = {}> = {

FILE: packages/types/src/schema/array.d.ts
  type ArraySchema (line 3) | interface ArraySchema<T extends SchemaType> extends SchemaType {
  type OptionalArraySchema (line 12) | interface OptionalArraySchema<T extends SchemaType>
  type DefaultArraySchema (line 18) | interface DefaultArraySchema<T extends SchemaType>

FILE: packages/types/src/schema/base.d.ts
  type SchemaDefinition (line 3) | interface SchemaDefinition {
  type ResponseSchemaDefinition (line 11) | interface ResponseSchemaDefinition {
  type InferSchemaRequest (line 15) | type InferSchemaRequest<T extends SchemaDefinition> = T extends {
  type SchemaType (line 32) | interface SchemaType {
  type InferType (line 40) | type InferType<T extends SchemaType> = T extends { _default: infer D }

FILE: packages/types/src/schema/boolean.d.ts
  type BooleanSchema (line 3) | interface BooleanSchema extends SchemaType {
  type OptionalBooleanSchema (line 9) | interface OptionalBooleanSchema
  type DefaultBooleanSchema (line 15) | interface DefaultBooleanSchema

FILE: packages/types/src/schema/jsonSchema.d.ts
  type StringFormat (line 1) | type StringFormat = "email" | "uuid" | "uri" | "date-time";
  type BaseJSONSchema (line 3) | interface BaseJSONSchema {
  type JSONSchemaString (line 8) | interface JSONSchemaString extends BaseJSONSchema {
  type JSONSchemaNumber (line 18) | interface JSONSchemaNumber extends BaseJSONSchema {
  type JSONSchemaBoolean (line 26) | interface JSONSchemaBoolean extends BaseJSONSchema {
  type JSONSchemaArray (line 31) | interface JSONSchemaArray extends BaseJSONSchema {
  type JSONSchemaObject (line 38) | interface JSONSchemaObject extends BaseJSONSchema {
  type JSONSchema (line 44) | type JSONSchema =
  type InferString (line 51) | type InferString<T extends JSONSchemaString> = T extends { const: infer C }
  type InferNumber (line 59) | type InferNumber<T extends JSONSchemaNumber> = T extends { const: infer C }
  type InferBoolean (line 67) | type InferBoolean<T extends JSONSchemaBoolean> = T extends { const: infe...
  type InferArray (line 71) | type InferArray<T extends JSONSchemaArray> = T extends { items: infer I }
  type InferObject (line 77) | type InferObject<T extends JSONSchemaObject> = T extends {
  type InferJSONSchemaType (line 102) | type InferJSONSchemaType<T> = T extends { default: infer D }
  type JSONSchemaDefinition (line 116) | interface JSONSchemaDefinition {
  type InferJSONSchemaRequest (line 126) | type InferJSONSchemaRequest<T extends JSONSchemaDefinition> = {

FILE: packages/types/src/schema/literal.d.ts
  type LiteralSchema (line 3) | interface LiteralSchema<T extends string | number | boolean>
  type OptionalLiteralSchema (line 10) | interface OptionalLiteralSchema<T extends string | number | boolean>
  type DefaultLiteralSchema (line 16) | interface DefaultLiteralSchema<T extends string | number | boolean>

FILE: packages/types/src/schema/number.d.ts
  type NumberSchema (line 3) | interface NumberSchema extends SchemaType {
  type OptionalNumberSchema (line 14) | interface OptionalNumberSchema
  type DefaultNumberSchema (line 20) | interface DefaultNumberSchema

FILE: packages/types/src/schema/object.d.ts
  type ObjectSchema (line 3) | interface ObjectSchema<T extends Record<string, SchemaType>>
  type OptionalObjectSchema (line 11) | interface OptionalObjectSchema<T extends Record<string, SchemaType>>
  type DefaultObjectSchema (line 17) | interface DefaultObjectSchema<T extends Record<string, SchemaType>>

FILE: packages/types/src/schema/string.d.ts
  type StringSchema (line 3) | interface StringSchema extends SchemaType {
  type OptionalStringSchema (line 16) | interface OptionalStringSchema
  type DefaultStringSchema (line 22) | interface DefaultStringSchema

FILE: packages/types/src/schema/union.d.ts
  type UnionSchema (line 3) | interface UnionSchema<T extends SchemaType[]> extends SchemaType {
  type OptionalUnionSchema (line 9) | interface OptionalUnionSchema<T extends SchemaType[]>
  type DefaultUnionSchema (line 15) | interface DefaultUnionSchema<T extends SchemaType[]>

FILE: packages/types/src/server.d.ts
  type ServerOptions (line 6) | interface ServerOptions {
  type KitoServerInstance (line 17) | interface KitoServerInstance<TExtensions = {}>
Condensed preview — 179 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (363K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1537,
    "preview": "name: Bug Report\ndescription: Report a problem or unexpected behavior in the project\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 863,
    "preview": "name: Feature Request\ndescription: Suggest a new idea or improvement\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\"]\nbody:\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 2040,
    "preview": "name: CI\n\non:\n  push:\n    branches: [main, dev]\n  pull_request:\n    branches: [main, dev]\n\njobs:\n  lint-and-test:\n    na"
  },
  {
    "path": ".github/workflows/doc-deploy.yml",
    "chars": 2036,
    "preview": "name: Deploy Docs\n\non:\n  push:\n    branches: [main]\n    paths:\n      - 'packages/kitojs/src/**'\n      - 'packages/types/"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 10785,
    "preview": "name: Release\n\npermissions:\n  contents: write\n  packages: write\n\non:\n  push:\n    tags:\n      - 'v*'\n  workflow_dispatch:"
  },
  {
    "path": ".gitignore",
    "chars": 41,
    "preview": "# typescript\nnode_modules\n\n# rust\n/target"
  },
  {
    "path": "Cargo.toml",
    "chars": 154,
    "preview": "[workspace]\nresolver = \"3\"\nmembers = [\"packages/core\", \"cli\"]\n\n[profile.release]\nlto = \"fat\"\ncodegen-units = 1\npanic = \""
  },
  {
    "path": "bench/cases/basic/elysia.ts",
    "chars": 404,
    "preview": "import { Elysia } from \"elysia\";\nimport { node } from \"@elysiajs/node\";\n\ndeclare const Bun: any;\n\nexport function start("
  },
  {
    "path": "bench/cases/basic/express.ts",
    "chars": 284,
    "preview": "import express from \"express\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = express();\n\n  "
  },
  {
    "path": "bench/cases/basic/fastify.ts",
    "chars": 302,
    "preview": "import Fastify from \"fastify\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = Fastify({\n    "
  },
  {
    "path": "bench/cases/basic/hapi.ts",
    "chars": 348,
    "preview": "import Hapi from \"@hapi/hapi\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = Hapi.server({ "
  },
  {
    "path": "bench/cases/basic/hono.ts",
    "chars": 523,
    "preview": "import { serve } from \"@hono/node-server\";\nimport { Hono } from \"hono\";\n\ndeclare const Bun: any;\n\nexport function start("
  },
  {
    "path": "bench/cases/basic/kito.ts",
    "chars": 260,
    "preview": "import { server } from \"kitojs\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = server();\n\n "
  },
  {
    "path": "bench/cases/basic/koa.ts",
    "chars": 405,
    "preview": "import Koa from \"koa\";\nimport Router from \"@koa/router\";\n\nexport function start(port: number): { stop: () => void } {\n  "
  },
  {
    "path": "bench/cases/basic/restify.ts",
    "chars": 298,
    "preview": "import restify from \"restify\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = restify.create"
  },
  {
    "path": "bench/cases/basic/tinyhttp.ts",
    "chars": 290,
    "preview": "import { App } from \"@tinyhttp/app\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = new App("
  },
  {
    "path": "bench/config.ts",
    "chars": 495,
    "preview": "type FrameworkConfig = string;\n\ntype FrameworkRuntime = \"bun\" | \"node\";\n\nexport default {\n  frameworks: [\n    \"kito\",\n  "
  },
  {
    "path": "bench/package.json",
    "chars": 947,
    "preview": "{\n  \"name\": \"@kitojs/bench\",\n  \"description\": \"Kito's benchmarks.\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": "
  },
  {
    "path": "bench/readme.md",
    "chars": 4753,
    "preview": "<img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-logo.svg\" width=\"2"
  },
  {
    "path": "bench/results/comparison-bun.json",
    "chars": 1588,
    "preview": "{\n  \"winner\": \"kito\",\n  \"runtime\": \"bun\",\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"mem"
  },
  {
    "path": "bench/results/comparison-node.json",
    "chars": 1744,
    "preview": "{\n  \"winner\": \"kito\",\n  \"runtime\": \"node\",\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"me"
  },
  {
    "path": "bench/results/data/bun/elysia.json",
    "chars": 424,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/express.json",
    "chars": 408,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/fastify.json",
    "chars": 409,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/hapi.json",
    "chars": 406,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/hono.json",
    "chars": 408,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/kito.json",
    "chars": 411,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/koa.json",
    "chars": 403,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/bun/tinyhttp.json",
    "chars": 410,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/elysia.json",
    "chars": 409,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/express.json",
    "chars": 410,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/fastify.json",
    "chars": 409,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/hapi.json",
    "chars": 407,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/hono.json",
    "chars": 406,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/kito.json",
    "chars": 411,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/koa.json",
    "chars": 406,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/restify.json",
    "chars": 410,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/results/data/node/tinyhttp.json",
    "chars": 411,
    "preview": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6."
  },
  {
    "path": "bench/runBench.ts",
    "chars": 8423,
    "preview": "import { runBenchmark } from \"./utils/http.ts\";\n\nimport config, { type FrameworkRuntime } from \"./config.ts\";\nconst { ho"
  },
  {
    "path": "bench/tsconfig.json",
    "chars": 180,
    "preview": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"allowImportingTsExtensions\": tru"
  },
  {
    "path": "bench/utils/chart.ts",
    "chars": 6225,
    "preview": "import {\n  BarController,\n  BarElement,\n  CategoryScale,\n  Chart,\n  LinearScale,\n  Title,\n  Tooltip,\n  Legend,\n} from \"c"
  },
  {
    "path": "bench/utils/frameworkRunner.ts",
    "chars": 985,
    "preview": "const [, , benchName, frameworkName, portArg] = process.argv;\n\nif (!benchName || !frameworkName || !portArg) {\n  console"
  },
  {
    "path": "bench/utils/http.ts",
    "chars": 1566,
    "preview": "import { exec } from \"node:child_process\";\nimport config from \"../config.ts\";\n\nconst { duration, connections } = config;"
  },
  {
    "path": "bench/utils/wait.ts",
    "chars": 530,
    "preview": "import net from \"node:net\";\n\nexport function waitForServerReady(port: number, retries = 50): Promise<void> {\n  return ne"
  },
  {
    "path": "biome.json",
    "chars": 621,
    "preview": "{\n  \"$schema\": \"https://biomejs.dev/schemas/2.2.3/schema.json\",\n  \"vcs\": {\n    \"enabled\": false,\n    \"clientKind\": \"git\""
  },
  {
    "path": "cli/.gitignore",
    "chars": 10,
    "preview": "bin/\ndist/"
  },
  {
    "path": "cli/Cargo.toml",
    "chars": 606,
    "preview": "[package]\nname = \"kito\"                                  # cli\nversion = \"0.1.0\"\nedition = \"2024\"\nauthors = [\"Nehuén <gi"
  },
  {
    "path": "cli/install.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "cli/package.json",
    "chars": 665,
    "preview": "{\n  \"name\": \"@kitojs/cli\",\n  \"version\": \"1.0.0\",\n  \"description\": \"🍄 Kito's official CLI.\",\n  \"bin\": {\n    \"kito\": \"bin/"
  },
  {
    "path": "cli/src/commands.rs",
    "chars": 172,
    "preview": "use crate::register_commands;\n\nuse async_trait::async_trait;\n\n#[async_trait]\npub(crate) trait Command {\n    async fn run"
  },
  {
    "path": "cli/src/main.rs",
    "chars": 768,
    "preview": "mod commands;\nmod utils;\n\nuse async_trait::async_trait;\nuse clap::{Parser, Subcommand};\n\nuse crate::commands::Command;\n\n"
  },
  {
    "path": "cli/src/utils.rs",
    "chars": 246,
    "preview": "#[macro_export]\nmacro_rules! register_commands {\n    ($($name:ident),*) => {\n        $(\n            pub(crate) mod $name"
  },
  {
    "path": "cliff.toml",
    "chars": 2029,
    "preview": "[changelog]\nbody = \"\"\"\n{% if version %}\\\n## [{{ version | trim_start_matches(pat=\"v\") }}] - {{ timestamp | date(format=\""
  },
  {
    "path": "examples/fluent/basic.ts",
    "chars": 111,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/clustering/index.ts",
    "chars": 340,
    "preview": "import cluster from \"node:cluster\";\nimport { availableParallelism } from \"node:os\";\n\nif (cluster.isPrimary) {\n  const nu"
  },
  {
    "path": "examples/fluent/clustering/server.ts",
    "chars": 246,
    "preview": "import { server } from \"kitojs\";\n\nserver({\n  reusePort: true, // this is required for clustering\n})\n  .get(\"/\", ({ res }"
  },
  {
    "path": "examples/fluent/extend.ts",
    "chars": 259,
    "preview": "import { server } from \"kitojs\";\n\ninterface Extends {\n  user: { id: string; name: string };\n}\n\nserver()\n  .extend<Extend"
  },
  {
    "path": "examples/fluent/file.ts",
    "chars": 358,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/download\", ({ res }) => {\n    res.sendFile(\"public/banner.png\", {\n  "
  },
  {
    "path": "examples/fluent/middlewares/index.ts",
    "chars": 215,
    "preview": "import { server } from \"kitojs\";\n\nimport { auth } from \"./samples/auth\";\nimport { logger } from \"./samples/logger\";\n\nser"
  },
  {
    "path": "examples/fluent/middlewares/samples/auth.ts",
    "chars": 279,
    "preview": "import { middleware } from \"kitojs\";\n\nexport const auth = middleware((ctx, next) => {\n  const { req, res } = ctx;\n  cons"
  },
  {
    "path": "examples/fluent/middlewares/samples/logger.ts",
    "chars": 231,
    "preview": "import { middleware } from \"kitojs\";\n\nexport const logger = middleware((ctx, next) => {\n  const { method, url } = ctx.re"
  },
  {
    "path": "examples/fluent/params.ts",
    "chars": 235,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/:id\", ({ req, res }) => res.send(req.params.id))\n  .get(\"/multi/:id/"
  },
  {
    "path": "examples/fluent/route.ts",
    "chars": 264,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .route(\"/\")\n  .get(({ res }) => {\n    res.send(\"hello world!\");\n  })\n  .pos"
  },
  {
    "path": "examples/fluent/router/cats.ts",
    "chars": 192,
    "preview": "import { router } from \"kitojs\";\n\nexport default router()\n  .get(\"/\", ({ res }) => {\n    res.send(\"hello cats!\");\n  })\n "
  },
  {
    "path": "examples/fluent/router/index.ts",
    "chars": 162,
    "preview": "import { server } from \"kitojs\";\nimport cats from \"./cats\";\n\nserver()\n  .mount(\"/cats\", cats)\n  .get(\"/\", ({ res }) => r"
  },
  {
    "path": "examples/fluent/schemas/builder.ts",
    "chars": 456,
    "preview": "import { schema, server, t } from \"kitojs\";\n\nconst userSchema = schema({\n  params: t.object({ id: t.str().uuid() }),\n  q"
  },
  {
    "path": "examples/fluent/schemas/json.ts",
    "chars": 774,
    "preview": "import { schema, server } from \"kitojs\";\n\nconst userSchema = schema.json({\n  params: {\n    type: \"object\",\n    propertie"
  },
  {
    "path": "examples/fluent/streaming/sse.ts",
    "chars": 258,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    const sse = res.sse();\n\n    sse.send(\"hello wo"
  },
  {
    "path": "examples/fluent/streaming/stream.ts",
    "chars": 301,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    const stream = res.stream();\n\n    stream.write"
  },
  {
    "path": "examples/fluent/unixSocket.ts",
    "chars": 157,
    "preview": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    res.send(\"Hello from Unix socket!\");\n  })\n  .l"
  },
  {
    "path": "examples/instance/basic.ts",
    "chars": 136,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"hello world!\");\n});\n\nap"
  },
  {
    "path": "examples/instance/clustering/index.ts",
    "chars": 340,
    "preview": "import cluster from \"node:cluster\";\nimport { availableParallelism } from \"node:os\";\n\nif (cluster.isPrimary) {\n  const nu"
  },
  {
    "path": "examples/instance/clustering/server.ts",
    "chars": 260,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server({\n  reusePort: true, // this is required for clustering\n});\n\napp.ge"
  },
  {
    "path": "examples/instance/extend.ts",
    "chars": 266,
    "preview": "import { server } from \"kitojs\";\n\ninterface Extends {\n  user: { id: string; name: string };\n}\n\nconst app = server().exte"
  },
  {
    "path": "examples/instance/file.ts",
    "chars": 375,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/download\", ({ res }) => {\n  res.sendFile(\"public/bann"
  },
  {
    "path": "examples/instance/middlewares/index.ts",
    "chars": 242,
    "preview": "import { server } from \"kitojs\";\n\nimport { auth } from \"./samples/auth\";\nimport { logger } from \"./samples/logger\";\n\ncon"
  },
  {
    "path": "examples/instance/middlewares/samples/auth.ts",
    "chars": 279,
    "preview": "import { middleware } from \"kitojs\";\n\nexport const auth = middleware((ctx, next) => {\n  const { req, res } = ctx;\n  cons"
  },
  {
    "path": "examples/instance/middlewares/samples/logger.ts",
    "chars": 231,
    "preview": "import { middleware } from \"kitojs\";\n\nexport const logger = middleware((ctx, next) => {\n  const { method, url } = ctx.re"
  },
  {
    "path": "examples/instance/params.ts",
    "chars": 257,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/:id\", ({ req, res }) => {\n  res.send(req.params.id);\n"
  },
  {
    "path": "examples/instance/route.ts",
    "chars": 290,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\nconst routes = app.route(\"/\");\n\nroutes.get(({ res }) => {\n  res."
  },
  {
    "path": "examples/instance/router/cats.ts",
    "chars": 212,
    "preview": "import { router } from \"kitojs\";\n\nconst cats = router();\n\ncats.get(\"/\", ({ res }) => {\n  res.send(\"hello cats!\");\n});\n\nc"
  },
  {
    "path": "examples/instance/router/index.ts",
    "chars": 189,
    "preview": "import { server } from \"kitojs\";\nimport cats from \"./cats\";\n\nconst app = server();\napp.mount(\"/cats\", cats);\n\napp.get(\"/"
  },
  {
    "path": "examples/instance/schemas/builder.ts",
    "chars": 513,
    "preview": "import { schema, server, t } from \"kitojs\";\n\nconst app = server();\n\nconst userSchema = schema({\n  params: t.object({ id:"
  },
  {
    "path": "examples/instance/schemas/json.ts",
    "chars": 772,
    "preview": "import { schema, server } from \"kitojs\";\n\nconst app = server();\n\nconst userSchema = schema.json({\n  params: {\n    type: "
  },
  {
    "path": "examples/instance/streaming/sse.ts",
    "chars": 256,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  const sse = res.sse();\n\n  sse.sen"
  },
  {
    "path": "examples/instance/streaming/stream.ts",
    "chars": 301,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  const stream = res.stream();\n\n  s"
  },
  {
    "path": "examples/instance/unixSocket.ts",
    "chars": 171,
    "preview": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"Hello from Unix socket!"
  },
  {
    "path": "examples/package.json",
    "chars": 301,
    "preview": "{\n  \"name\": \"@kitojs/examples\",\n  \"description\": \"Kito's usage examples.\",\n  \"private\": true,\n  \"type\": \"module\",\n\n  \"sc"
  },
  {
    "path": "examples/runExample.ts",
    "chars": 1594,
    "preview": "#!/usr/bin/env tsx\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURL"
  },
  {
    "path": "examples/tsconfig.json",
    "chars": 183,
    "preview": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {},\n  \"include\": [\"instance/**/*\", \"fluent/**/*\"],\n  \"refer"
  },
  {
    "path": "lefthook.yml",
    "chars": 5531,
    "preview": "skip_output:\n  - meta\n  - summary\n\npre-commit:\n  parallel: true\n  commands:\n    # Rust commands\n    fmt-check:\n      tag"
  },
  {
    "path": "license",
    "chars": 1062,
    "preview": "MIT License\n\nCopyright (c) 2024 kitojs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
  },
  {
    "path": "package.json",
    "chars": 836,
    "preview": "{\n  \"name\": \"kito\",\n  \"version\": \"1.0.0\",\n  \"description\": \"The Kito's workspace.\",\n  \"scripts\": {\n    \"fmt\": \"biome for"
  },
  {
    "path": "packages/core/.gitignore",
    "chars": 5,
    "preview": "dist/"
  },
  {
    "path": "packages/core/Cargo.toml",
    "chars": 767,
    "preview": "[package]\nname = \"core\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[lib]\nname = \"core\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\n"
  },
  {
    "path": "packages/core/build.rs",
    "chars": 39,
    "preview": "fn main() {\n    napi_build::setup();\n}\n"
  },
  {
    "path": "packages/core/package.json",
    "chars": 1133,
    "preview": "{\n  \"name\": \"@kitojs/kito-core\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"Internal logic (core) of the Kito frame"
  },
  {
    "path": "packages/core/src/http/cookies.rs",
    "chars": 1116,
    "preview": "#[derive(Clone, Default)]\n#[napi(object)]\npub struct CookieOptionsCore {\n    pub domain: Option<String>,\n    pub http_on"
  },
  {
    "path": "packages/core/src/http/cookies_tests.rs",
    "chars": 3859,
    "preview": "#[cfg(test)]\nmod tests {\n    use super::super::cookies::*;\n\n    #[test]\n    fn test_basic_cookie() {\n        let options"
  },
  {
    "path": "packages/core/src/http/files.rs",
    "chars": 2020,
    "preview": "use hyper::body::Bytes;\n\nuse std::{collections::HashMap, time::UNIX_EPOCH};\nuse tokio::{fs::File, io::AsyncReadExt};\n\nus"
  },
  {
    "path": "packages/core/src/http/mime.rs",
    "chars": 1012,
    "preview": "use std::path::Path;\n\npub fn get_mime_type(path: &str) -> &'static str {\n    let extension = Path::new(path).extension()"
  },
  {
    "path": "packages/core/src/http/mime_tests.rs",
    "chars": 2400,
    "preview": "#[cfg(test)]\nmod tests {\n    use super::super::mime::get_mime_type;\n\n    #[test]\n    fn test_html_mime_types() {\n       "
  },
  {
    "path": "packages/core/src/http/request.rs",
    "chars": 6164,
    "preview": "use http_body_util::BodyExt;\nuse hyper::{\n    Request,\n    body::{Bytes, Incoming},\n};\n\nuse napi::bindgen_prelude::{Buff"
  },
  {
    "path": "packages/core/src/http/response.rs",
    "chars": 4305,
    "preview": "use http_body_util::{Full, StreamBody, combinators::BoxBody};\nuse hyper::body::{Bytes, Frame};\n\nuse napi::bindgen_prelud"
  },
  {
    "path": "packages/core/src/http.rs",
    "chars": 124,
    "preview": "pub mod cookies;\npub mod cookies_tests;\npub mod files;\npub mod mime;\npub mod mime_tests;\npub mod request;\npub mod respon"
  },
  {
    "path": "packages/core/src/lib.rs",
    "chars": 90,
    "preview": "#[macro_use]\nextern crate napi_derive;\n\npub mod http;\npub mod server;\npub mod validation;\n"
  },
  {
    "path": "packages/core/src/server/context.rs",
    "chars": 607,
    "preview": "use crate::http::{request::RequestCore, response::ResponseChannel};\nuse napi::{\n    Env,\n    bindgen_prelude::{External,"
  },
  {
    "path": "packages/core/src/server/core.rs",
    "chars": 6101,
    "preview": "use hyper::server::conn::http1;\nuse hyper_util::rt::TokioIo;\n\nuse napi::threadsafe_function::{ThreadsafeFunction, Thread"
  },
  {
    "path": "packages/core/src/server/handler.rs",
    "chars": 9923,
    "preview": "use http_body_util::{BodyExt, Full, StreamBody};\nuse hyper::{\n    Request, Response,\n    body::{Bytes, Frame, Incoming},"
  },
  {
    "path": "packages/core/src/server/router.rs",
    "chars": 3194,
    "preview": "use ahash::AHashMap;\nuse matchit::{Match, Router as MatchitRouter};\nuse parking_lot::RwLock;\nuse std::sync::Arc;\n\nuse su"
  },
  {
    "path": "packages/core/src/server/routes.rs",
    "chars": 6070,
    "preview": "use ahash::HashMap;\nuse std::sync::Arc;\n\nuse http_body_util::Full;\nuse hyper::Response;\nuse hyper::body::Bytes;\n\nuse nap"
  },
  {
    "path": "packages/core/src/server.rs",
    "chars": 199,
    "preview": "pub mod context;\npub mod core;\npub mod handler;\npub mod router;\npub mod routes;\n\npub use core::ServerCore;\npub use route"
  },
  {
    "path": "packages/core/src/validation/parser.rs",
    "chars": 1905,
    "preview": "use serde_json::{Map, Value, from_slice};\n\nuse super::types::*;\nuse crate::validation::validate_value;\n\nuse std::collect"
  },
  {
    "path": "packages/core/src/validation/parser_tests.rs",
    "chars": 5575,
    "preview": "#[cfg(test)]\nmod tests {\n    use super::super::parser::*;\n    use super::super::types::*;\n    use serde_json::json;\n    "
  },
  {
    "path": "packages/core/src/validation/tests.rs",
    "chars": 6225,
    "preview": "#[cfg(test)]\nmod tests {\n    use super::super::{types::*, validators::*};\n    use serde_json::{Value, json};\n    use std"
  },
  {
    "path": "packages/core/src/validation/types.rs",
    "chars": 1972,
    "preview": "use serde::{Deserialize, Serialize};\nuse serde_json::Value;\n\nuse std::collections::HashMap;\n\n#[derive(Debug, Clone, Dese"
  },
  {
    "path": "packages/core/src/validation/validators.rs",
    "chars": 11623,
    "preview": "use super::types::*;\n\nuse regex::Regex;\nuse serde_json::{Map, Number, Value};\n\npub fn validate_string(\n    value: &str,\n"
  },
  {
    "path": "packages/core/src/validation.rs",
    "chars": 149,
    "preview": "pub mod parser;\npub mod parser_tests;\npub mod tests;\npub mod types;\npub mod validators;\n\npub use parser::*;\npub use type"
  },
  {
    "path": "packages/core/tsconfig.json",
    "chars": 135,
    "preview": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"],\n  \"ref"
  },
  {
    "path": "packages/kitojs/.gitignore",
    "chars": 11,
    "preview": "dist/\ndocs/"
  },
  {
    "path": "packages/kitojs/package.json",
    "chars": 1306,
    "preview": "{\n  \"name\": \"kitojs\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"🐺 The high-performance, type-safe and modern TypeS"
  },
  {
    "path": "packages/kitojs/readme.md",
    "chars": 2238,
    "preview": "<div align=\"center\">\n  <img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/"
  },
  {
    "path": "packages/kitojs/src/helpers/middleware.ts",
    "chars": 1492,
    "preview": "import type { MiddlewareDefinition, MiddlewareHandler } from \"@kitojs/types\";\n\n/**\n * Creates a typed middleware definit"
  },
  {
    "path": "packages/kitojs/src/helpers/schema.ts",
    "chars": 3114,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  SchemaDefinition,\n  JSONSchemaDefinition,\n  InferJSON"
  },
  {
    "path": "packages/kitojs/src/index.ts",
    "chars": 1823,
    "preview": "/**\n * @module kitojs\n *\n * Kito is a high-performance, type-safe TypeScript web framework with a Rust core.\n *\n * @exam"
  },
  {
    "path": "packages/kitojs/src/schemas/builders.ts",
    "chars": 4807,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport { StringSchemaImpl } from \"./primitives/string\";\nimport { Numb"
  },
  {
    "path": "packages/kitojs/src/schemas/index.ts",
    "chars": 339,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nexport * from \"./builders\";\n\nexport * from \"./primitives/string\";\nexp"
  },
  {
    "path": "packages/kitojs/src/schemas/jsonSchema.ts",
    "chars": 5907,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  SchemaType,\n  JSONSchema,\n  JSONSchemaString,\n  JSONS"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/array.ts",
    "chars": 1515,
    "preview": "import type { ArraySchema, SchemaType } from \"@kitojs/types\";\n\nexport class ArraySchemaImpl<T extends SchemaType> implem"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/boolean.ts",
    "chars": 806,
    "preview": "import type { BooleanSchema } from \"@kitojs/types\";\n\nexport class BooleanSchemaImpl implements BooleanSchema {\n  _type!:"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/literal.ts",
    "chars": 897,
    "preview": "import type { LiteralSchema } from \"@kitojs/types\";\n\nexport class LiteralSchemaImpl<T extends string | number | boolean>"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/number.ts",
    "chars": 1435,
    "preview": "import type { NumberSchema } from \"@kitojs/types\";\n\nexport class NumberSchemaImpl implements NumberSchema {\n  _type!: nu"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/object.ts",
    "chars": 1228,
    "preview": "import type { InferType, ObjectSchema, SchemaType } from \"@kitojs/types\";\n\nexport class ObjectSchemaImpl<T extends Recor"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/string.ts",
    "chars": 1689,
    "preview": "import type { StringSchema } from \"@kitojs/types\";\n\nexport class StringSchemaImpl implements StringSchema {\n  _type!: st"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/union.ts",
    "chars": 1042,
    "preview": "import type { SchemaType, UnionSchema } from \"@kitojs/types\";\n\nexport class UnionSchemaImpl<T extends SchemaType[]> impl"
  },
  {
    "path": "packages/kitojs/src/server/analyzer.ts",
    "chars": 6725,
    "preview": "import * as acorn from \"acorn\";\nimport * as walk from \"acorn-walk\";\n\nexport type StaticResponseType =\n  | { type: \"none\""
  },
  {
    "path": "packages/kitojs/src/server/request.ts",
    "chars": 5038,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  CommonHeaderNames,\n  KitoRequest,\n  RequestHeaders,\n}"
  },
  {
    "path": "packages/kitojs/src/server/response.ts",
    "chars": 13704,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  KitoResponse,\n  CookieOptions,\n  SendFileOptions,\n  C"
  },
  {
    "path": "packages/kitojs/src/server/router.ts",
    "chars": 23798,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  HttpMethod,\n  MiddlewareDefinition,\n  SchemaDefinitio"
  },
  {
    "path": "packages/kitojs/src/server/server.ts",
    "chars": 13443,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  HttpMethod,\n  MiddlewareDefinition,\n  SchemaDefinitio"
  },
  {
    "path": "packages/kitojs/src/types.ts",
    "chars": 577,
    "preview": "export type { Context, KitoContext } from \"@kitojs/types\";\n\nexport type {\n  CommonHeaderNames,\n  RequestHeaders,\n  Parse"
  },
  {
    "path": "packages/kitojs/tests/analyzer.test.ts",
    "chars": 3962,
    "preview": "import { describe, expect, it } from \"vitest\";\n\nimport { analyzeHandler } from \"../src/server/analyzer\";\nimport type { C"
  },
  {
    "path": "packages/kitojs/tests/middleware.test.ts",
    "chars": 3212,
    "preview": "import { describe, expect, it } from \"vitest\";\nimport { middleware } from \"../src\";\n\ndescribe(\"Middleware Helper\", () =>"
  },
  {
    "path": "packages/kitojs/tests/route-chain.test.ts",
    "chars": 6972,
    "preview": "import type { SchemaDefinition } from \"@kitojs/types\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { middl"
  },
  {
    "path": "packages/kitojs/tests/router.test.ts",
    "chars": 18109,
    "preview": "import type { Route } from \"@kitojs/kito-core\";\nimport type { MiddlewareDefinition } from \"@kitojs/types\";\nimport { desc"
  },
  {
    "path": "packages/kitojs/tests/schema-helper.test.ts",
    "chars": 2089,
    "preview": "import { describe, expect, it } from \"vitest\";\nimport { schema, t } from \"../src\";\n\ndescribe(\"Schema Helper\", () => {\n  "
  },
  {
    "path": "packages/kitojs/tests/server.test.ts",
    "chars": 4341,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport { describe, it, expect, beforeEach, afterEach } from \"vitest\";"
  },
  {
    "path": "packages/kitojs/tests/types.test.ts",
    "chars": 3594,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport { describe, expectTypeOf, it } from \"vitest\";\nimport { server,"
  },
  {
    "path": "packages/kitojs/tsconfig.json",
    "chars": 180,
    "preview": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"],\n  \"ref"
  },
  {
    "path": "packages/kitojs/tsdown.config.ts",
    "chars": 194,
    "preview": "import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n  entry: \"src/index.ts\",\n  outDir: \"dist\",\n\n  form"
  },
  {
    "path": "packages/kitojs/typedoc.json",
    "chars": 924,
    "preview": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/index.ts\"],\n  \"out\": \"docs\",\n  \"plugin\": [],\n  "
  },
  {
    "path": "packages/kitojs/vitest.config.ts",
    "chars": 397,
    "preview": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environmen"
  },
  {
    "path": "packages/readme.md",
    "chars": 2956,
    "preview": "<img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-logo.svg\" width=\"2"
  },
  {
    "path": "packages/types/.gitignore",
    "chars": 5,
    "preview": "dist/"
  },
  {
    "path": "packages/types/package.json",
    "chars": 766,
    "preview": "{\n  \"name\": \"@kitojs/types\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"TypeScript types for the Kito framework.\",\n"
  },
  {
    "path": "packages/types/src/context.d.ts",
    "chars": 563,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nimport type { KitoRequest } from \"./http/request\";\nimport type { Kito"
  },
  {
    "path": "packages/types/src/handlers.d.ts",
    "chars": 447,
    "preview": "import type { KitoContext } from \"./context\";\n\nexport type NextFunction = () => void | Promise<void>;\n\nexport type Middl"
  },
  {
    "path": "packages/types/src/http/request.d.ts",
    "chars": 1850,
    "preview": "export type CommonHeaderNames =\n  | \"accept\"\n  | \"accept-encoding\"\n  | \"accept-language\"\n  | \"authorization\"\n  | \"cache-"
  },
  {
    "path": "packages/types/src/http/response.d.ts",
    "chars": 3414,
    "preview": "import type { InferType, SchemaType } from \"../schema/base\";\n\nexport type CommonResponseHeaderNames =\n  | \"content-type\""
  },
  {
    "path": "packages/types/src/index.d.ts",
    "chars": 549,
    "preview": "// biome-ignore assist/source/organizeImports: ...\nexport * from \"./http/request\";\nexport * from \"./http/response\";\nexpo"
  },
  {
    "path": "packages/types/src/router.d.ts",
    "chars": 8167,
    "preview": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { MiddlewareDefinition, RouteChain } from"
  },
  {
    "path": "packages/types/src/routes.d.ts",
    "chars": 7911,
    "preview": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { SchemaDefinition } from \"./schema/base\""
  },
  {
    "path": "packages/types/src/schema/array.d.ts",
    "chars": 728,
    "preview": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface ArraySchema<T extends SchemaType> extends SchemaT"
  },
  {
    "path": "packages/types/src/schema/base.d.ts",
    "chars": 1181,
    "preview": "import type { RequestHeaders } from \"../http/request\";\n\nexport interface SchemaDefinition {\n  params?: SchemaType;\n  que"
  },
  {
    "path": "packages/types/src/schema/boolean.d.ts",
    "chars": 504,
    "preview": "import type { SchemaType } from \"./base\";\n\nexport interface BooleanSchema extends SchemaType {\n  _type: boolean;\n  optio"
  },
  {
    "path": "packages/types/src/schema/jsonSchema.d.ts",
    "chars": 3507,
    "preview": "type StringFormat = \"email\" | \"uuid\" | \"uri\" | \"date-time\";\n\ninterface BaseJSONSchema {\n  description?: string;\n  defaul"
  },
  {
    "path": "packages/types/src/schema/literal.d.ts",
    "chars": 608,
    "preview": "import type { SchemaType } from \"./base\";\n\nexport interface LiteralSchema<T extends string | number | boolean>\n  extends"
  },
  {
    "path": "packages/types/src/schema/number.d.ts",
    "chars": 643,
    "preview": "import type { SchemaType } from \"./base\";\n\nexport interface NumberSchema extends SchemaType {\n  _type: number;\n  min(val"
  },
  {
    "path": "packages/types/src/schema/object.d.ts",
    "chars": 762,
    "preview": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface ObjectSchema<T extends Record<string, SchemaType>"
  },
  {
    "path": "packages/types/src/schema/string.d.ts",
    "chars": 718,
    "preview": "import type { SchemaType } from \"./base\";\n\nexport interface StringSchema extends SchemaType {\n  _type: string;\n  min(len"
  },
  {
    "path": "packages/types/src/schema/union.d.ts",
    "chars": 638,
    "preview": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface UnionSchema<T extends SchemaType[]> extends Schem"
  },
  {
    "path": "packages/types/src/server.d.ts",
    "chars": 911,
    "preview": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { MiddlewareDefinition, RouteChain } from"
  },
  {
    "path": "packages/types/tsconfig.json",
    "chars": 148,
    "preview": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"emitDeclarationOnly\": true\n"
  },
  {
    "path": "packages/types/tsdown.config.ts",
    "chars": 196,
    "preview": "import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n  entry: \"src/index.d.ts\",\n  outDir: \"dist\",\n\n  fo"
  },
  {
    "path": "pnpm-workspace.yaml",
    "chars": 87,
    "preview": "packages:\n  - packages/*\n  - examples\n  - bench\n\nonlyBuiltDependencies:\n  - skia-canvas"
  },
  {
    "path": "readme.md",
    "chars": 2323,
    "preview": "<div align=\"center\">\n  <img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/"
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 82,
    "preview": "[toolchain]\nchannel = \"stable\"\ncomponents = [\"clippy\", \"rustfmt\", \"rust-analyzer\"]"
  },
  {
    "path": "rustfmt.toml",
    "chars": 188,
    "preview": "edition = \"2024\"\n\nmax_width = 100\n\nhard_tabs = false\ntab_spaces = 4\n\nnewline_style = \"Unix\"\nuse_small_heuristics = \"Max\""
  },
  {
    "path": "tsconfig.base.json",
    "chars": 540,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"declaratio"
  }
]

About this extraction

This page contains the full source code of the kitojs/kito GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 179 files (325.7 KB), approximately 87.6k tokens, and a symbol index with 408 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!