[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: Report a problem or unexpected behavior in the project\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to report a bug!\n\n  - type: input\n    id: version\n    attributes:\n      label: Version\n      description: What version are you using?\n      placeholder: e.g. 1.0.0-alpha.4\n    validations:\n      required: true\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Description of the issue\n      description: Explain what happened and what you expected to happen\n      placeholder: \"Describe the bug here\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to reproduce\n      description: Provide steps so we can reproduce the issue\n      placeholder: |\n        1. Run ...\n        2. Call ...\n        3. Observe ...\n    validations:\n      required: true\n\n  - type: textarea\n    id: logs\n    attributes:\n      label: Logs or error messages\n      description: Paste any relevant logs, stack traces, or console output\n      render: shell\n\n  - type: textarea\n    id: environment\n    attributes:\n      label: Environment\n      description: Describe your environment\n      placeholder: |\n        OS:\n        Runtime (Node/Bun/Deno):\n        CPU:\n        Additional details:\n\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      options:\n        - label: I have searched existing issues\n        - label: I am using the latest version\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Suggest a new idea or improvement\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\"]\nbody:\n  - type: textarea\n    id: summary\n    attributes:\n      label: Summary\n      description: Briefly describe the feature you'd like to see\n    validations:\n      required: true\n\n  - type: textarea\n    id: motivation\n    attributes:\n      label: Motivation\n      description: Why is this feature important? What problem does it solve?\n    validations:\n      required: true\n\n  - type: textarea\n    id: proposal\n    attributes:\n      label: Proposed Solution\n      description: Describe how this feature could be implemented or how you'd expect it to behave\n\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      options:\n        - label: I've searched for related issues\n        - label: I've read the documentation\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [main, dev]\n  pull_request:\n    branches: [main, dev]\n\njobs:\n  lint-and-test:\n    name: Lint & Test\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 8\n\n      - name: Get pnpm store directory\n        shell: bash\n        run: |\n          echo \"STORE_PATH=$(pnpm store path --silent)\" >> $GITHUB_ENV\n\n      - name: Setup pnpm cache\n        uses: actions/cache@v4\n        with:\n          path: ${{ env.STORE_PATH }}\n          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}\n          restore-keys: |\n            ${{ runner.os }}-pnpm-store-\n\n      - name: Install dependencies\n        run: pnpm install -r\n\n      - name: Build\n        run: pnpm build\n\n      - name: Test TypeScript\n        run: pnpm test\n        working-directory: packages/kitojs\n\n  rust-test:\n    name: Rust Tests\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Rust\n        uses: actions-rust-lang/setup-rust-toolchain@v1\n        with:\n          toolchain: stable\n\n      - name: Cache Rust dependencies\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.cargo/bin/\n            ~/.cargo/registry/index/\n            ~/.cargo/registry/cache/\n            ~/.cargo/git/db/\n            packages/core/target/\n          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}\n          restore-keys: |\n            ${{ runner.os }}-cargo-\n\n      - name: Run Rust tests\n        run: cargo test --verbose\n        working-directory: packages/core\n\n      - name: Check Rust formatting\n        run: cargo fmt -- --check\n        working-directory: packages/core\n\n      - name: Run Clippy\n        run: cargo clippy -- -D warnings\n        working-directory: packages/core"
  },
  {
    "path": ".github/workflows/doc-deploy.yml",
    "content": "name: Deploy Docs\n\non:\n  push:\n    branches: [main]\n    paths:\n      - 'packages/kitojs/src/**'\n      - 'packages/types/src/**'\n  workflow_dispatch:\n\njobs:\n  deploy-docs:\n    name: Generate and Deploy API Docs\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout kito repo\n        uses: actions/checkout@v4\n        with:\n          path: kito\n\n      - name: Checkout web repo\n        uses: actions/checkout@v4\n        with:\n          repository: kitojs/web\n          token: ${{ secrets.WEB_REPO_TOKEN }}\n          path: web\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 8\n\n      - name: Install kito dependencies\n        run: pnpm install -r --ignore-scripts\n        working-directory: kito\n\n      - name: Build kito packages\n        run: pnpm build\n        working-directory: kito\n\n      - name: Install TypeDoc in kitojs package\n        run: pnpm add -D typedoc\n        working-directory: kito/packages/kitojs\n        \n      - name: Generate TypeDoc\n        working-directory: kito\n        run: |\n          cd packages/kitojs\n          pnpm exec typedoc\n\n      - name: Copy docs to web repo\n        run: |\n          # Remove old API docs if they exist\n          rm -rf web/public/api\n          \n          # Copy new generated docs\n          mkdir -p web/public/api\n          cp -r kito/packages/kitojs/docs/* web/public/api/\n          \n          # Verify files were copied\n          ls -la web/public/api/\n\n      - name: Commit and push to web repo\n        working-directory: web\n        run: |\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"github-actions[bot]@users.noreply.github.com\"\n          \n          git add public/api\n          \n          if git diff --staged --quiet; then\n            echo \"No changes to commit\"\n          else\n            git commit -m \"docs: update API documentation\"\n            git push\n          fi"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\npermissions:\n  contents: write\n  packages: write\n\non:\n  push:\n    tags:\n      - 'v*'\n  workflow_dispatch:\n\njobs:\n  build-napi:\n    name: Build NAPI - ${{ matrix.settings.target }}\n    strategy:\n      fail-fast: false\n      matrix:\n        settings:\n          - host: macos-latest\n            target: x86_64-apple-darwin\n            build: pnpm core:build --target x86_64-apple-darwin\n          - host: macos-latest\n            target: aarch64-apple-darwin\n            build: pnpm core:build --target aarch64-apple-darwin\n          - host: windows-latest\n            target: x86_64-pc-windows-msvc\n            build: pnpm core:build --target x86_64-pc-windows-msvc\n          - host: windows-latest\n            target: i686-pc-windows-msvc\n            build: pnpm core:build --target i686-pc-windows-msvc\n          - host: windows-latest\n            target: aarch64-pc-windows-msvc\n            build: pnpm core:build --target aarch64-pc-windows-msvc\n          - host: ubuntu-latest\n            target: x86_64-unknown-linux-gnu\n            build: pnpm core:build --target x86_64-unknown-linux-gnu --use-napi-cross\n          - host: ubuntu-latest\n            target: x86_64-unknown-linux-musl\n            build: pnpm core:build --target x86_64-unknown-linux-musl -x\n          - host: ubuntu-latest\n            target: aarch64-unknown-linux-gnu\n            build: pnpm core:build --target aarch64-unknown-linux-gnu --use-napi-cross\n          - host: ubuntu-latest\n            target: aarch64-unknown-linux-musl\n            build: pnpm core:build --target aarch64-unknown-linux-musl -x\n          - host: ubuntu-latest\n            target: armv7-unknown-linux-gnueabihf\n            build: pnpm core:build --target armv7-unknown-linux-gnueabihf --use-napi-cross\n    runs-on: ${{ matrix.settings.host }}\n    steps:\n      - uses: actions/checkout@v5\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version: '20'\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 8\n\n      - name: Install Rust toolchain\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          toolchain: stable\n          targets: ${{ matrix.settings.target }}\n          components: clippy, rustfmt\n\n      - name: Install build dependencies (Linux only)\n        if: runner.os == 'Linux'\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y build-essential musl-tools clang pkg-config libssl-dev\n\n      - name: Setup zig (required for musl / cargo-zigbuild)\n        if: ${{ contains(matrix.settings.target, 'musl') }}\n        uses: mlugg/setup-zig@v2\n        with:\n          version: '0.15.2'\n\n      - name: Install cargo-zigbuild (musl only)\n        if: ${{ contains(matrix.settings.target, 'musl') }}\n        uses: taiki-e/install-action@v2\n        with:\n          tool: cargo-zigbuild\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Install dependencies\n        run: pnpm install -r\n\n      - name: Build NAPI binary\n        run: ${{ matrix.settings.build }}\n        working-directory: .\n        shell: bash\n\n      - name: List built files\n        run: ls -la packages/core/dist/\n        shell: bash\n\n      - name: Upload artifact\n        uses: actions/upload-artifact@v5\n        with:\n          name: bindings-${{ matrix.settings.target }}\n          path: packages/core/dist/*.node\n          if-no-files-found: error\n\n  build-freebsd:\n    runs-on: ubuntu-latest\n    name: Build NAPI - FreeBSD\n    steps:\n      - uses: actions/checkout@v5\n      \n      - name: Build on FreeBSD\n        id: build\n        uses: cross-platform-actions/action@v0.30.0\n        env:\n          DEBUG: napi:*\n          RUSTUP_IO_THREADS: 1\n        with:\n          operating_system: freebsd\n          version: '14.3'\n          memory: 8G\n          cpu_count: 3\n          environment_variables: 'DEBUG RUSTUP_IO_THREADS'\n          shell: bash\n          run: |\n            sudo pkg install -y -f curl node libnghttp2 npm\n            sudo npm install -g corepack\n            curl https://sh.rustup.rs -sSf --output rustup.sh\n            sh rustup.sh -y --profile minimal --default-toolchain stable\n            sudo corepack enable\n            source \"$HOME/.cargo/env\"\n            echo \"~~~~ rustc --version ~~~~\"\n            rustc --version\n            echo \"~~~~ node -v ~~~~\"\n            node -v\n            echo \"~~~~ pnpm --version ~~~~\"\n            pnpm --version\n            pwd\n            ls -lah\n            whoami\n            env\n            freebsd-version\n            pnpm install -r --filter '!bench' --filter '!examples'\n            pnpm core:build\n            rm -rf node_modules\n            rm -rf target\n      \n      - name: Upload artifact\n        uses: actions/upload-artifact@v5\n        with:\n          name: bindings-x86_64-unknown-freebsd\n          path: packages/core/dist/*.node\n          if-no-files-found: error\n\n  publish-npm:\n    name: Publish to NPM\n    runs-on: ubuntu-latest\n    needs: \n      - build-napi\n      - build-freebsd\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          registry-url: 'https://registry.npmjs.org'\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 8\n\n      - name: Install dependencies\n        run: pnpm install -r\n\n      - name: Download all artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: artifacts\n\n      - name: List all downloaded artifacts\n        run: |\n          echo \"-- Downloaded artifacts structure --\"\n          ls -laR artifacts/\n\n      - name: Create dist directory for core\n        run: mkdir -p packages/core/dist\n\n      - name: Move all .node binaries to core dist\n        run: |\n          echo \"-- Moving .node files --\"\n          for artifact_dir in artifacts/bindings-*; do\n            if [ -d \"$artifact_dir\" ]; then\n              target=$(basename \"$artifact_dir\" | sed 's/^bindings-//')\n              echo \"Processing target: $target\"\n\n              node_file=$(find \"$artifact_dir\" -name \"*.node\" -type f)\n              if [ -n \"$node_file\" ]; then\n                case \"$target\" in\n                  x86_64-apple-darwin)\n                    dest_name=\"core.darwin-x64.node\"\n                    ;;\n                  aarch64-apple-darwin)\n                    dest_name=\"core.darwin-arm64.node\"\n                    ;;\n                  x86_64-pc-windows-msvc)\n                    dest_name=\"core.win32-x64-msvc.node\"\n                    ;;\n                  i686-pc-windows-msvc)\n                    dest_name=\"core.win32-ia32-msvc.node\"\n                    ;;\n                  aarch64-pc-windows-msvc)\n                    dest_name=\"core.win32-arm64-msvc.node\"\n                    ;;\n                  x86_64-unknown-linux-gnu)\n                    dest_name=\"core.linux-x64-gnu.node\"\n                    ;;\n                  x86_64-unknown-linux-musl)\n                    dest_name=\"core.linux-x64-musl.node\"\n                    ;;\n                  aarch64-unknown-linux-gnu)\n                    dest_name=\"core.linux-arm64-gnu.node\"\n                    ;;\n                  aarch64-unknown-linux-musl)\n                    dest_name=\"core.linux-arm64-musl.node\"\n                    ;;\n                  armv7-unknown-linux-gnueabihf)\n                    dest_name=\"core.linux-arm-gnueabihf.node\"\n                    ;;\n                  x86_64-unknown-freebsd)\n                    dest_name=\"core.freebsd-x64.node\"\n                    ;;\n                  *)\n                    echo \"Warning: Unknown target $target, using generic name\"\n                    dest_name=\"core.$target.node\"\n                    ;;\n                esac\n                \n                echo \"  Copying: $node_file -> packages/core/dist/$dest_name\"\n                cp -v \"$node_file\" \"packages/core/dist/$dest_name\"\n              else\n                echo \"  Warning: No .node file found in $artifact_dir\"\n              fi\n            fi\n          done\n          echo \"-- Final dist contents --\"\n          ls -la packages/core/dist/\n\n      - name: Build NAPI index files\n        run: |\n          cd packages/core\n          pnpm napi build --platform --release --esm --const-enum --output-dir dist\n        shell: bash\n\n      - name: Verify core package structure\n        run: |\n          echo \"-- Core package dist/ contents --\"\n          ls -la packages/core/dist/\n          echo \"-- Checking for required files --\"\n          test -f packages/core/dist/index.js && echo \"✓ index.js found\" || echo \"✗ index.js missing\"\n          test -f packages/core/dist/index.d.ts && echo \"✓ index.d.ts found\" || echo \"✗ index.d.ts missing\"\n          echo \"-- .node files --\"\n          find packages/core/dist/ -name \"*.node\" -exec basename {} \\;\n\n      - name: Build TypeScript packages\n        run: pnpm ts:build\n\n      - name: Publish @kitojs/kito-core\n        run: pnpm publish --access public --no-git-checks\n        working-directory: packages/core\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n      - name: Publish @kitojs/types\n        run: pnpm publish --access public --no-git-checks\n        working-directory: packages/types\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n      - name: Publish kitojs\n        run: pnpm publish --access public --no-git-checks\n        working-directory: packages/kitojs\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n  create-release:\n    name: Create GitHub Release\n    runs-on: ubuntu-latest\n    needs: publish-npm\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Extract version from tag\n        id: version\n        run: echo \"VERSION=${GITHUB_REF#refs/tags/v}\" >> $GITHUB_OUTPUT\n\n      - name: Create Release\n        uses: softprops/action-gh-release@v2\n        with:\n          tag_name: ${{ github.ref_name }}\n          name: Release ${{ github.ref_name }}\n          body: |\n            ## 🐺 Kito ${{ steps.version.outputs.VERSION }}\n            \n            ### Installation\n            ```bash\n            npm install kitojs@${{ steps.version.outputs.VERSION }}\n            # or\n            pnpm add kitojs@${{ steps.version.outputs.VERSION }}\n            ```\n            \n            ### What's Changed\n            See the changelog for details.\n            \n            ### Documentation\n            Visit kito.pages.dev for full documentation.\n          draft: false\n          prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# typescript\nnode_modules\n\n# rust\n/target"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"3\"\nmembers = [\"packages/core\", \"cli\"]\n\n[profile.release]\nlto = \"fat\"\ncodegen-units = 1\npanic = \"abort\"\nopt-level = 3\nstrip = true\n"
  },
  {
    "path": "bench/cases/basic/elysia.ts",
    "content": "import { Elysia } from \"elysia\";\nimport { node } from \"@elysiajs/node\";\n\ndeclare const Bun: any;\n\nexport function start(port: number): { stop: () => void } {\n  const isBun = typeof Bun !== \"undefined\";\n\n  const app = isBun ? new Elysia() : new Elysia({ adapter: node() });\n\n  app.get(\"/\", () => \"hello world!\");\n\n  const server = app.listen(port);\n\n  return {\n    stop: async () => server.stop(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/express.ts",
    "content": "import express from \"express\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = express();\n\n  app.get(\"/\", (req, res) => {\n    res.send(\"hello world!\");\n  });\n\n  const appListen = app.listen(port);\n\n  return {\n    stop: async () => appListen.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/fastify.ts",
    "content": "import Fastify from \"fastify\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = Fastify({\n    logger: false,\n  });\n\n  app.get(\"/\", (request, reply) => {\n    reply.send(\"hello world!\");\n  });\n\n  app.listen({ port });\n\n  return {\n    stop: async () => await app.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/hapi.ts",
    "content": "import Hapi from \"@hapi/hapi\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = Hapi.server({ port });\n\n  app.route({\n    method: \"GET\",\n    path: \"/\",\n    handler: (request, h) => {\n      return \"hello world!\";\n    },\n  });\n\n  (async () => await app.start())();\n\n  return {\n    stop: async () => await app.stop(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/hono.ts",
    "content": "import { serve } from \"@hono/node-server\";\nimport { Hono } from \"hono\";\n\ndeclare const Bun: any;\n\nexport function start(port: number): { stop: () => void } {\n  const app = new Hono();\n\n  app.get(\"/\", (c) => c.text(\"hello world!\"));\n\n  if (typeof Bun !== \"undefined\") {\n    const server = Bun.serve({\n      fetch: app.fetch,\n      port,\n    });\n\n    return {\n      stop: () => server.stop(),\n    };\n  }\n\n  const server = serve({\n    fetch: app.fetch,\n    port,\n  });\n\n  return {\n    stop: async () => server.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/kito.ts",
    "content": "import { server } from \"kitojs\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = server();\n\n  app.get(\"/\", (ctx) => {\n    ctx.res.send(\"hello world!\");\n  });\n\n  app.listen(port);\n\n  return {\n    stop: async () => app.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/koa.ts",
    "content": "import Koa from \"koa\";\nimport Router from \"@koa/router\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = new Koa();\n  const router = new Router();\n\n  router.get(\"/\", (ctx) => {\n    ctx.body = \"hello world!\";\n  });\n\n  app.use(router.routes());\n  app.use(router.allowedMethods());\n\n  const appListen = app.listen(port);\n\n  return {\n    stop: async () => appListen.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/restify.ts",
    "content": "import restify from \"restify\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = restify.createServer();\n\n  app.get(\"/\", (req, res, next) => {\n    res.send(\"hello world!\");\n    return next();\n  });\n\n  app.listen(port);\n\n  return {\n    stop: async () => app.close(),\n  };\n}\n"
  },
  {
    "path": "bench/cases/basic/tinyhttp.ts",
    "content": "import { App } from \"@tinyhttp/app\";\n\nexport function start(port: number): { stop: () => void } {\n  const app = new App();\n\n  app.get(\"/\", (req, res) => {\n    res.send(\"hello world!\");\n  });\n\n  const appListen = app.listen(port);\n\n  return {\n    stop: async () => appListen.close(),\n  };\n}\n"
  },
  {
    "path": "bench/config.ts",
    "content": "type FrameworkConfig = string;\n\ntype FrameworkRuntime = \"bun\" | \"node\";\n\nexport default {\n  frameworks: [\n    \"kito\",\n    \"elysia\",\n    \"express\",\n    \"fastify\",\n    \"hono\",\n    \"restify\",\n    \"tinyhttp\",\n    \"koa\",\n    \"hapi\",\n  ] satisfies FrameworkConfig[],\n  hostname: \"localhost\",\n\n  connections: 100,\n  pipelining: 10,\n  duration: 30,\n  workers: undefined,\n\n  chart: {\n    enabled: true,\n    output: \"results/charts/result.png\",\n  },\n};\n\nexport type { FrameworkConfig, FrameworkRuntime };\n"
  },
  {
    "path": "bench/package.json",
    "content": "{\n  \"name\": \"@kitojs/bench\",\n  \"description\": \"Kito's benchmarks.\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"bench:run\": \"bun run runBench.ts\",\n    \"bench:node\": \"bun run runBench.ts --exclude-runtime=bun\",\n    \"bench:bun\": \"bun run runBench.ts --exclude-runtime=node\"\n  },\n  \"dependencies\": {\n    \"@elysiajs/node\": \"^1.4.2\",\n    \"@hapi/hapi\": \"^21.4.3\",\n    \"@hono/node-server\": \"^1.19.6\",\n    \"@koa/router\": \"^14.0.0\",\n    \"@tinyhttp/app\": \"^3.0.1\",\n    \"chart.js\": \"^4.5.1\",\n    \"elysia\": \"^1.4.16\",\n    \"express\": \"^5.1.0\",\n    \"fastify\": \"^5.6.1\",\n    \"hono\": \"^4.10.4\",\n    \"kitojs\": \"workspace:*\",\n    \"koa\": \"^3.1.1\",\n    \"restify\": \"^11.1.0\",\n    \"skia-canvas\": \"^3.0.8\"\n  },\n  \"devDependencies\": {\n    \"@types/autocannon\": \"^7.12.7\",\n    \"@types/express\": \"^5.0.5\",\n    \"@types/koa\": \"^3.0.1\",\n    \"@types/koa__router\": \"^12.0.5\",\n    \"@types/restify\": \"^8.5.12\",\n    \"tsx\": \"^4.20.6\",\n    \"typescript\": \"^5.9.2\"\n  }\n}\n"
  },
  {
    "path": "bench/readme.md",
    "content": "<img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-logo.svg\" width=\"200px\" align=\"right\" />\n\n# Kito - `benchmarks`\n\nPerformance benchmarks comparing Kito against popular Node.js web frameworks.\n\n---\n\n## 📊 Latest Results\n\n![Benchmark Results](results/charts/result-node.png)\n\n> **Note:** Benchmarks are automatically updated on each release.\n\n---\n\n## 🎯 Benchmarked Frameworks\n\n- **Kito** - High-performance TypeScript framework written in Rust\n- **Fastify** - Fast and low overhead web framework\n- **Hono** - Fast web framework for the edge\n- **Express** - Fast, unopinionated web framework\n- **Koa** - Expressive middleware framework\n- **Restify** - REST API framework\n- **TinyHTTP** - Lightweight Express-like framework\n- **Hapi** - Rich framework for building applications\n\n---\n\n## 🔧 Benchmark Configuration\n\n```typescript\n{\n  connections: 100,\n  pipelining: 10,\n  duration: 30, // seconds\n  workers: undefined // auto\n}\n```\n\nAll frameworks are tested with a simple \"Hello World\" endpoint to measure raw performance.\n\n---\n\n## 🚀 Running Benchmarks\n\n### Prerequisites\n\n```bash\npnpm install\n```\n\n### Run All Benchmarks\n\n```bash\npnpm bench:run basic\n```\n\nThis will:\n1. Start each framework on sequential ports (3000, 3001, ...)\n2. Run [wrk](https://github.com/wg/wrk) load tests\n3. Generate comparison charts\n4. Save detailed results to `results/data/`\n\n### Mixing Node and Bun runtimes\n\nSome framework adapters only work on Node.js while others can run under Bun. You can pin the runtime per framework in `config.ts`:\n\n```ts\nframeworks: [\n  { name: \"kito\", runtime: \"bun\" },\n  { name: \"elysia\", runtime: \"bun\" },\n  { name: \"restify\", runtime: \"node\" },\n  \"koa\", // uses whichever runtime you launch the runner with\n];\n```\n\n- Default (string) entries execute inside the same runtime that starts `runBench.ts`.\n- `runtime: \"bun\"` executes via `pnpm dlx bun run ...`, so make sure `pnpm` is available (it will download Bun on demand).\n- `runtime: \"node\"` executes via `pnpm dlx tsx ...`, so no local CLI install is required beyond `pnpm`.\n\n---\n\n## 📁 Project Structure\n\n```\nbench/\n├── cases/\n│   └── basic/           # Basic \"Hello World\" benchmarks\n│       ├── kito.ts\n│       ├── fastify.ts\n│       ├── express.ts\n│       └── ...\n├── results/\n│   ├── charts/          # Generated benchmark charts\n│   └── data/            # Raw JSON results\n├── utils/\n│   ├── http.ts          # Wrk runner\n│   └── chart.ts         # Chart generation\n├── config.ts            # Benchmark configuration\n└── runBench.ts          # Main benchmark runner\n```\n\n---\n\n## 📈 Metrics Measured\n\n- **Requests/sec** - Average requests per second\n- **Latency (ms)** - Average response time in milliseconds\n- **Throughput (bytes/sec)** - Average data throughput\n\n---\n\n## 🎨 Adding New Benchmarks\n\n1. Create a new folder in `cases/` (e.g., `cases/routing/`)\n2. Add framework implementations following the pattern:\n\n```typescript\nexport function start(port: number): { stop: () => void } {\n  const app = createServer();\n  \n  app.get(\"/\", handler);\n  app.listen(port);\n  \n  return {\n    stop: async () => app.close(),\n  };\n}\n```\n\n3. Run your benchmark:\n\n```bash\npnpm bench:run routing\n```\n\n---\n\n## 📊 Understanding Results\n\n### Requests/sec (Higher is better)\nNumber of requests the server can handle per second.\n\n### Latency (Lower is better)\nTime taken to receive a response. Includes network and processing time.\n\n### Throughput (Higher is better)\nAmount of data transferred per second.\n\n---\n\n## ⚙️ Configuration\n\nEdit `config.ts` to customize:\n\n```typescript\nexport default {\n  frameworks: [\"kito\", \"fastify\", \"hono\", ...],\n  connections: 100,      // Concurrent connections\n  pipelining: 10,        // Requests per connection\n  duration: 30,          // Test duration in seconds\n  chart: {\n    enabled: true,\n    output: \"results/charts/result.png\"\n  }\n};\n```\n\n---\n\n## 🔬 Methodology\n\n- All tests run on the same machine with identical conditions\n- Each framework uses its recommended setup and defaults\n- Tests measure only the framework overhead, not business logic\n- Results are averaged over the test duration\n\n---\n\n## 📝 Notes\n\n- Benchmarks are indicative and may vary based on hardware\n- Real-world performance depends on application complexity\n- These tests measure raw throughput, not production scenarios\n- All frameworks are excellent choices for different use cases\n\n---\n\n## 🤝 Contributing\n\nFound an issue with the benchmarks? Want to add a new framework?\n\n1. Fork the repository\n2. Add your changes\n3. Run the benchmarks locally\n4. Submit a pull request\n\n---\n\n## 📄 License\n\nLicensed under the [MIT License](../license).\n\n---\n\n[![blazingly fast](https://blazingly.fast/api/badge.svg?repo=kitojs%2Fkito)](https://blazingly.fast)\n"
  },
  {
    "path": "bench/results/comparison-bun.json",
    "content": "{\n  \"winner\": \"kito\",\n  \"runtime\": \"bun\",\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"ranking\": [\n    {\n      \"rank\": 1,\n      \"framework\": \"kito\",\n      \"requests\": 283106.67,\n      \"latency\": 0.39031,\n      \"throughput\": 32275169.28,\n      \"difference\": \"0%\"\n    },\n    {\n      \"rank\": 2,\n      \"framework\": \"elysia\",\n      \"requests\": 149351.06,\n      \"latency\": 0.6690900000000001,\n      \"throughput\": 19115540.48,\n      \"difference\": \"-47.25%\"\n    },\n    {\n      \"rank\": 3,\n      \"framework\": \"hono\",\n      \"requests\": 104550.49,\n      \"latency\": 0.96,\n      \"throughput\": 13379829.76,\n      \"difference\": \"-63.07%\"\n    },\n    {\n      \"rank\": 4,\n      \"framework\": \"fastify\",\n      \"requests\": 58216.12,\n      \"latency\": 1.72,\n      \"throughput\": 7507804.16,\n      \"difference\": \"-79.44%\"\n    },\n    {\n      \"rank\": 5,\n      \"framework\": \"tinyhttp\",\n      \"requests\": 40612.94,\n      \"latency\": 2.46,\n      \"throughput\": 7843348.48,\n      \"difference\": \"-85.65%\"\n    },\n    {\n      \"rank\": 6,\n      \"framework\": \"express\",\n      \"requests\": 36992.17,\n      \"latency\": 2.7,\n      \"throughput\": 7098859.52,\n      \"difference\": \"-86.93%\"\n    },\n    {\n      \"rank\": 7,\n      \"framework\": \"koa\",\n      \"requests\": 32931.2,\n      \"latency\": 3.03,\n      \"throughput\": 4246732.8,\n      \"difference\": \"-88.37%\"\n    },\n    {\n      \"rank\": 8,\n      \"framework\": \"hapi\",\n      \"requests\": 25239.19,\n      \"latency\": 3.96,\n      \"throughput\": 4414504.96,\n      \"difference\": \"-91.08%\"\n    }\n  ]\n}\n"
  },
  {
    "path": "bench/results/comparison-node.json",
    "content": "{\n  \"winner\": \"kito\",\n  \"runtime\": \"node\",\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"ranking\": [\n    {\n      \"rank\": 1,\n      \"framework\": \"kito\",\n      \"requests\": 282020.9,\n      \"latency\": 0.38923,\n      \"throughput\": 32149340.16,\n      \"difference\": \"0%\"\n    },\n    {\n      \"rank\": 2,\n      \"framework\": \"fastify\",\n      \"requests\": 42597.14,\n      \"latency\": 2.7,\n      \"throughput\": 7539261.44,\n      \"difference\": \"-84.90%\"\n    },\n    {\n      \"rank\": 3,\n      \"framework\": \"hono\",\n      \"requests\": 37869.16,\n      \"latency\": 3.2,\n      \"throughput\": 6668943.36,\n      \"difference\": \"-86.57%\"\n    },\n    {\n      \"rank\": 4,\n      \"framework\": \"koa\",\n      \"requests\": 28399.52,\n      \"latency\": 4.14,\n      \"throughput\": 5001707.52,\n      \"difference\": \"-89.93%\"\n    },\n    {\n      \"rank\": 5,\n      \"framework\": \"restify\",\n      \"requests\": 26687.06,\n      \"latency\": 4.31,\n      \"throughput\": 4959764.48,\n      \"difference\": \"-90.54%\"\n    },\n    {\n      \"rank\": 6,\n      \"framework\": \"hapi\",\n      \"requests\": 26628.01,\n      \"latency\": 4.48,\n      \"throughput\": 5913968.64,\n      \"difference\": \"-90.56%\"\n    },\n    {\n      \"rank\": 7,\n      \"framework\": \"tinyhttp\",\n      \"requests\": 24126.25,\n      \"latency\": 4.89,\n      \"throughput\": 5788139.52,\n      \"difference\": \"-91.45%\"\n    },\n    {\n      \"rank\": 8,\n      \"framework\": \"elysia\",\n      \"requests\": 15821.79,\n      \"latency\": 7.81,\n      \"throughput\": 2548039.68,\n      \"difference\": \"-94.39%\"\n    },\n    {\n      \"rank\": 9,\n      \"framework\": \"express\",\n      \"requests\": 9914.66,\n      \"latency\": 12.59,\n      \"throughput\": 2369781.76,\n      \"difference\": \"-96.48%\"\n    }\n  ]\n}\n"
  },
  {
    "path": "bench/results/data/bun/elysia.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"elysia\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 149351.06\n    },\n    \"latency\": {\n      \"average\": 0.6690900000000001\n    },\n    \"throughput\": {\n      \"average\": 19115540.48\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/express.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"express\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 36992.17\n    },\n    \"latency\": {\n      \"average\": 2.7\n    },\n    \"throughput\": {\n      \"average\": 7098859.52\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/fastify.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"fastify\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 58216.12\n    },\n    \"latency\": {\n      \"average\": 1.72\n    },\n    \"throughput\": {\n      \"average\": 7507804.16\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/hapi.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"hapi\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 25239.19\n    },\n    \"latency\": {\n      \"average\": 3.96\n    },\n    \"throughput\": {\n      \"average\": 4414504.96\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/hono.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"hono\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 104550.49\n    },\n    \"latency\": {\n      \"average\": 0.96\n    },\n    \"throughput\": {\n      \"average\": 13379829.76\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/kito.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"kito\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 283106.67\n    },\n    \"latency\": {\n      \"average\": 0.39031\n    },\n    \"throughput\": {\n      \"average\": 32275169.28\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/koa.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"koa\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 32931.2\n    },\n    \"latency\": {\n      \"average\": 3.03\n    },\n    \"throughput\": {\n      \"average\": 4246732.8\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/bun/tinyhttp.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"bun\",\n  \"framework\": \"tinyhttp\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 40612.94\n    },\n    \"latency\": {\n      \"average\": 2.46\n    },\n    \"throughput\": {\n      \"average\": 7843348.48\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/elysia.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"elysia\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 15821.79\n    },\n    \"latency\": {\n      \"average\": 7.81\n    },\n    \"throughput\": {\n      \"average\": 2548039.68\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/express.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"express\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 9914.66\n    },\n    \"latency\": {\n      \"average\": 12.59\n    },\n    \"throughput\": {\n      \"average\": 2369781.76\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/fastify.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"fastify\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 42597.14\n    },\n    \"latency\": {\n      \"average\": 2.7\n    },\n    \"throughput\": {\n      \"average\": 7539261.44\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/hapi.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"hapi\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 26628.01\n    },\n    \"latency\": {\n      \"average\": 4.48\n    },\n    \"throughput\": {\n      \"average\": 5913968.64\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/hono.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"hono\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 37869.16\n    },\n    \"latency\": {\n      \"average\": 3.2\n    },\n    \"throughput\": {\n      \"average\": 6668943.36\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/kito.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"kito\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 282020.9\n    },\n    \"latency\": {\n      \"average\": 0.38923\n    },\n    \"throughput\": {\n      \"average\": 32149340.16\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/koa.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"koa\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 28399.52\n    },\n    \"latency\": {\n      \"average\": 4.14\n    },\n    \"throughput\": {\n      \"average\": 5001707.52\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/restify.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"restify\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 26687.06\n    },\n    \"latency\": {\n      \"average\": 4.31\n    },\n    \"throughput\": {\n      \"average\": 4959764.48\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/results/data/node/tinyhttp.json",
    "content": "{\n  \"machine\": {\n    \"cpu\": \"Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz\",\n    \"memory\": \"31 GB\",\n    \"platform\": \"linux 6.12.48-1-MANJARO\"\n  },\n  \"runtime\": \"node\",\n  \"framework\": \"tinyhttp\",\n  \"results\": {\n    \"requests\": {\n      \"average\": 24126.25\n    },\n    \"latency\": {\n      \"average\": 4.89\n    },\n    \"throughput\": {\n      \"average\": 5788139.52\n    }\n  },\n  \"previousResults\": null,\n  \"comparison\": null\n}\n"
  },
  {
    "path": "bench/runBench.ts",
    "content": "import { runBenchmark } from \"./utils/http.ts\";\n\nimport config, { type FrameworkRuntime } from \"./config.ts\";\nconst { hostname, frameworks, chart } = config;\n\nimport { generateChart } from \"./utils/chart.ts\";\nimport { waitForServerReady } from \"./utils/wait.ts\";\n\nimport fs from \"node:fs\";\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\ntype BenchmarkResult = {\n  framework: string;\n  result: {\n    requests: { average: number };\n    latency: { average: number };\n    throughput: { average: number };\n  };\n};\n\ntype RunningBenchmark = {\n  stop: () => Promise<void> | void;\n};\n\ntype NormalizedFramework = {\n  name: string;\n  runtime: FrameworkRuntime;\n};\n\nconst CURRENT_RUNTIME: FrameworkRuntime =\n  typeof (globalThis as { Bun?: unknown }).Bun !== \"undefined\" ? \"bun\" : \"node\";\n\nconst PROJECT_ROOT = path.dirname(fileURLToPath(import.meta.url));\nconst RUNNER_ENTRY = path.join(PROJECT_ROOT, \"utils\", \"frameworkRunner.ts\");\nconst PNPM_BIN = process.platform === \"win32\" ? \"pnpm.cmd\" : \"pnpm\";\n\nasync function launchFramework(\n  benchName: string,\n  framework: NormalizedFramework,\n  port: number,\n): Promise<RunningBenchmark> {\n  if (framework.runtime === CURRENT_RUNTIME) {\n    const mod = await import(`./cases/${benchName}/${framework.name}.ts`);\n    const bench = mod.default || mod;\n    const instance: RunningBenchmark = bench.start(port);\n\n    return {\n      stop: async () => {\n        if (typeof instance?.stop === \"function\") {\n          await instance.stop();\n        }\n      },\n    };\n  }\n\n  const child = spawnFrameworkProcess(\n    framework.runtime,\n    benchName,\n    framework.name,\n    port,\n  );\n\n  return {\n    stop: async () => await stopChildProcess(child),\n  };\n}\n\nfunction spawnFrameworkProcess(\n  targetRuntime: FrameworkRuntime,\n  benchName: string,\n  frameworkName: string,\n  port: number,\n): ChildProcess {\n  if (targetRuntime === \"node\") {\n    return spawn(\n      PNPM_BIN,\n      [\"dlx\", \"tsx\", RUNNER_ENTRY, benchName, frameworkName, String(port)],\n      {\n        stdio: \"inherit\",\n        cwd: PROJECT_ROOT,\n      },\n    );\n  }\n\n  return spawn(\n    PNPM_BIN,\n    [\"dlx\", \"bun\", \"run\", RUNNER_ENTRY, benchName, frameworkName, String(port)],\n    {\n      stdio: \"inherit\",\n      cwd: PROJECT_ROOT,\n    },\n  );\n}\n\nasync function stopChildProcess(child: ChildProcess): Promise<void> {\n  if (!child.killed) {\n    child.kill(\"SIGTERM\");\n  }\n\n  await new Promise<void>((resolve, reject) => {\n    child.once(\"error\", reject);\n    child.once(\"exit\", (code, signal) => {\n      if (code === 0 || signal === \"SIGTERM\") {\n        resolve();\n      } else {\n        reject(\n          new Error(`Framework runner exited with code ${code ?? \"null\"}`),\n        );\n      }\n    });\n  });\n}\n\nfunction getMachineSpecs() {\n  const cpu = os.cpus()[0].model;\n  const memory = `${Math.round(os.totalmem() / 1024 / 1024 / 1024)} GB`;\n  const platform = `${os.platform()} ${os.release()}`;\n\n  return { cpu, memory, platform };\n}\n\nasync function main() {\n  const benchName = process.argv[2];\n  if (!benchName) {\n    console.error(\n      \"You must pass the name of the benchmark, e.g.: pnpm bench:run basic\",\n    );\n    process.exit(1);\n  }\n\n  const args = process.argv.slice(3);\n  const excludeRuntimes =\n    args\n      .find((arg) => arg.startsWith(\"--exclude-runtime=\"))\n      ?.split(\"=\")[1]\n      ?.split(\",\") || [];\n\n  const excludeFrameworks =\n    args\n      .find((arg) => arg.startsWith(\"--exclude-framework=\"))\n      ?.split(\"=\")[1]\n      ?.split(\",\") || [];\n\n  const runtimes: FrameworkRuntime[] = [\"node\", \"bun\"].filter(\n    (r) => !excludeRuntimes.includes(r),\n  ) as FrameworkRuntime[];\n\n  const machine = getMachineSpecs();\n\n  for (const runtime of runtimes) {\n    console.log(`\\n${\"-\".repeat(40)}`);\n    console.log(`Running benchmarks on ${runtime.toUpperCase()} runtime`);\n    console.log(`${\"-\".repeat(40)}\\n`);\n\n    const results: BenchmarkResult[] = [];\n    let port = 3000;\n\n    for (const frameworkName of frameworks) {\n      if (excludeFrameworks.includes(frameworkName)) {\n        console.log(`Skipping ${frameworkName} (excluded via flag)`);\n        continue;\n      }\n\n      if (runtime === \"bun\" && frameworkName === \"restify\") {\n        console.log(\n          `Skipping ${frameworkName} (not compatible with Bun runtime)`,\n        );\n\n        continue;\n      }\n\n      const framework: NormalizedFramework = {\n        name: frameworkName,\n        runtime: runtime,\n      };\n\n      const benchInstance = await launchFramework(benchName, framework, port);\n      await waitForServerReady(port);\n\n      console.log(\n        `Running benchmark for ${framework.name} (runtime: ${framework.runtime})...`,\n      );\n      const URL = `http://${hostname}:${port}`;\n\n      const result = await runBenchmark(URL);\n      results.push({ framework: framework.name, result });\n\n      port++;\n\n      await benchInstance.stop();\n    }\n\n    console.table(\n      results.map(({ framework, result }) => ({\n        Framework: framework,\n        \"Requests/sec\": result.requests.average,\n        \"Latency (ms)\": result.latency.average,\n        \"Throughput (bytes/sec)\": result.throughput.average,\n      })),\n    );\n\n    if (chart?.enabled) {\n      const output =\n        chart.output?.replace(\"result.png\", `result-${runtime}.png`) ||\n        `results/charts/result-${runtime}.png`;\n      await generateChart(\n        {\n          frameworks: results.map((r) => r.framework),\n          requests: results.map((r) => r.result.requests.average),\n          latency: results.map((r) => r.result.latency.average),\n          throughput: results.map((r) => r.result.throughput.average),\n        },\n        output,\n        runtime,\n      );\n    }\n\n    for (const result of results) {\n      const OUTPUT_PATH = `results/data/${runtime}`;\n      const FILE_PATH = `${OUTPUT_PATH}/${result.framework}.json`;\n\n      let previousResults = null;\n      let comparison = null;\n\n      if (fs.existsSync(FILE_PATH)) {\n        try {\n          const content = JSON.parse(fs.readFileSync(FILE_PATH, \"utf-8\"));\n          if (content.results) {\n            previousResults = content.results;\n\n            const calcDiff = (current: number, previous: number) => {\n              const diff = ((current - previous) / previous) * 100;\n              return `${diff > 0 ? \"+\" : \"\"}${diff.toFixed(2)}%`;\n            };\n\n            comparison = {\n              requests: calcDiff(\n                result.result.requests.average,\n                previousResults.requests.average,\n              ),\n              latency: calcDiff(\n                result.result.latency.average,\n                previousResults.latency.average,\n              ),\n              throughput: calcDiff(\n                result.result.throughput.average,\n                previousResults.throughput.average,\n              ),\n            };\n          }\n        } catch (_) {}\n      }\n\n      const outputData = {\n        machine,\n        runtime,\n        framework: result.framework,\n        results: result.result,\n        previousResults,\n        comparison,\n      };\n\n      const data = JSON.stringify(outputData, null, \"\\t\");\n\n      if (!fs.existsSync(OUTPUT_PATH)) {\n        fs.mkdirSync(OUTPUT_PATH, { recursive: true });\n      }\n\n      fs.writeFileSync(FILE_PATH, data);\n    }\n\n    const sortedResults = [...results].sort(\n      (a, b) => b.result.requests.average - a.result.requests.average,\n    );\n\n    const winner = sortedResults[0];\n\n    const ranking = sortedResults.map((item, index) => {\n      const diff =\n        ((item.result.requests.average - winner.result.requests.average) /\n          winner.result.requests.average) *\n        100;\n\n      return {\n        rank: index + 1,\n        framework: item.framework,\n        requests: item.result.requests.average,\n        latency: item.result.latency.average,\n        throughput: item.result.throughput.average,\n        difference: index === 0 ? \"0%\" : `${diff.toFixed(2)}%`,\n      };\n    });\n\n    const leaderboard = {\n      winner: winner.framework,\n      runtime,\n      machine,\n      ranking,\n    };\n\n    fs.writeFileSync(\n      `results/comparison-${runtime}.json`,\n      JSON.stringify(leaderboard, null, \"\\t\"),\n    );\n  }\n\n  console.log(`\\n${\"-\".repeat(40)}`);\n  console.log(\"✅ All benchmarks completed!\");\n  console.log(`${\"-\".repeat(40)}\\n`);\n\n  process.exit(0);\n}\n\n(async () => await main())();\n"
  },
  {
    "path": "bench/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"allowImportingTsExtensions\": true\n  },\n  \"references\": [{ \"path\": \"../packages/kitojs\" }]\n}\n"
  },
  {
    "path": "bench/utils/chart.ts",
    "content": "import {\n  BarController,\n  BarElement,\n  CategoryScale,\n  Chart,\n  LinearScale,\n  Title,\n  Tooltip,\n  Legend,\n} from \"chart.js\";\nimport { Canvas } from \"skia-canvas\";\nimport fs from \"node:fs/promises\";\n\nChart.register([\n  BarController,\n  BarElement,\n  CategoryScale,\n  LinearScale,\n  Title,\n  Tooltip,\n  Legend,\n]);\n\ntype ChartData = {\n  frameworks: string[];\n  requests: number[];\n  latency: number[];\n  throughput: number[];\n};\n\nexport async function generateChart(\n  data: ChartData,\n  outputPath: string,\n  runtime?: string,\n) {\n  try {\n    const canvas = new Canvas(1000, 600);\n\n    const colors = [\n      \"#3b82f6\", // blue\n      \"#10b981\", // green\n      \"#f59e0b\", // amber\n      \"#8b5cf6\", // purple\n      \"#ec4899\", // pink\n      \"#06b6d4\", // cyan\n    ];\n\n    const chart = new Chart(canvas as any, {\n      type: \"bar\",\n      data: {\n        labels: data.frameworks.map(\n          (f) => f.charAt(0).toUpperCase() + f.slice(1),\n        ),\n        datasets: [\n          {\n            label: \"Requests/sec\",\n            data: data.requests,\n            backgroundColor: \"#3b82f6\",\n            borderRadius: 8,\n            borderSkipped: false,\n          },\n          {\n            label: \"Latency (ms)\",\n            data: data.latency,\n            backgroundColor: \"#10b981\",\n            borderRadius: 8,\n            borderSkipped: false,\n            yAxisID: \"y1\",\n          },\n        ],\n      },\n      options: {\n        responsive: false,\n        layout: {\n          padding: {\n            top: 20,\n            bottom: 20,\n            left: 20,\n            right: 20,\n          },\n        },\n        plugins: {\n          legend: {\n            display: true,\n            position: \"top\",\n            align: \"end\",\n            labels: {\n              color: \"#1f2937\",\n              font: {\n                size: 14,\n                weight: 600,\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n              padding: 15,\n              usePointStyle: true,\n              pointStyle: \"rectRounded\",\n            },\n          },\n          title: {\n            display: true,\n            text: runtime\n              ? `Benchmark Results - ${runtime.toUpperCase()}`\n              : \"Benchmark Results\",\n            color: \"#1f2937\",\n            font: {\n              size: 28,\n              weight: \"bold\",\n              family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n            },\n            padding: {\n              top: 10,\n              bottom: 30,\n            },\n          },\n          tooltip: {\n            backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n            titleFont: {\n              size: 14,\n              weight: \"bold\",\n              family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n            },\n            bodyFont: {\n              size: 13,\n              family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n            },\n            padding: 12,\n            cornerRadius: 8,\n            displayColors: false,\n            callbacks: {\n              label: (context) => {\n                const label = context.dataset.label || \"\";\n                const value = context.parsed.y;\n\n                if (label.includes(\"Latency\")) {\n                  return `${label}: ${value?.toFixed(2)} ms`;\n                }\n\n                return `${label}: ${value?.toLocaleString()} req/s`;\n              },\n            },\n          },\n        },\n        scales: {\n          x: {\n            grid: {\n              display: false,\n            },\n            ticks: {\n              color: \"#4b5563\",\n              font: {\n                size: 16,\n                weight: 600,\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n              padding: 10,\n            },\n            border: {\n              display: false,\n            },\n          },\n          y: {\n            beginAtZero: true,\n            position: \"left\",\n            grid: {\n              color: \"#e5e7eb\",\n              lineWidth: 1,\n            },\n            ticks: {\n              color: \"#3b82f6\",\n              font: {\n                size: 13,\n                weight: 600,\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n              padding: 10,\n              callback: (value) => {\n                return value.toLocaleString();\n              },\n            },\n            border: {\n              display: false,\n            },\n            title: {\n              display: true,\n              text: \"Requests/sec\",\n              color: \"#3b82f6\",\n              font: {\n                size: 13,\n                weight: \"bold\",\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n            },\n          },\n          y1: {\n            beginAtZero: true,\n            position: \"right\",\n            grid: {\n              display: false,\n            },\n            ticks: {\n              color: \"#10b981\",\n              font: {\n                size: 13,\n                weight: 600,\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n              padding: 10,\n              callback: (value) => {\n                let valueNumber = value as number;\n                return valueNumber.toFixed(1);\n              },\n            },\n            border: {\n              display: false,\n            },\n            title: {\n              display: true,\n              text: \"Latency (ms)\",\n              color: \"#10b981\",\n              font: {\n                size: 13,\n                weight: \"bold\",\n                family: \"'Inter', 'Segoe UI', 'Helvetica Neue', sans-serif\",\n              },\n            },\n          },\n        },\n      },\n    });\n\n    const dir = outputPath.substring(0, outputPath.lastIndexOf(\"/\"));\n    if (dir) {\n      await fs.mkdir(dir, { recursive: true });\n    }\n\n    const pngBuffer = await canvas.toBuffer(\"png\", {\n      matte: \"white\",\n      density: 2,\n    });\n\n    await fs.writeFile(outputPath, pngBuffer);\n\n    console.log(`✅ Chart saved to ${outputPath}`);\n\n    chart.destroy();\n  } catch (err) {\n    console.error(\"Error generating chart:\", err);\n  }\n}\n"
  },
  {
    "path": "bench/utils/frameworkRunner.ts",
    "content": "const [, , benchName, frameworkName, portArg] = process.argv;\n\nif (!benchName || !frameworkName || !portArg) {\n  console.error(\n    \"Missing arguments. Usage: frameworkRunner <bench> <framework> <port>\",\n  );\n  process.exit(1);\n}\n\nconst port = Number(portArg);\nif (!Number.isFinite(port)) {\n  console.error(`Invalid port provided to frameworkRunner: ${portArg}`);\n  process.exit(1);\n}\n\nconst mod = await import(`../cases/${benchName}/${frameworkName}.ts`);\nconst bench = mod.default || mod;\nconst instance = bench.start(port);\n\nasync function shutdown(code = 0) {\n  try {\n    if (typeof instance?.stop === \"function\") {\n      await instance.stop();\n    }\n  } catch (error) {\n    console.error(\"Failed to stop framework cleanly\", error);\n  } finally {\n    process.exit(code);\n  }\n}\n\nprocess.on(\"SIGTERM\", () => void shutdown());\nprocess.on(\"SIGINT\", () => void shutdown());\nprocess.on(\"uncaughtException\", async (error) => {\n  console.error(error);\n  await shutdown(1);\n});\n\nexport {};\n"
  },
  {
    "path": "bench/utils/http.ts",
    "content": "import { exec } from \"node:child_process\";\nimport config from \"../config.ts\";\n\nconst { duration, connections } = config;\n\nexport type WrkResult = {\n  requests: { average: number };\n  latency: { average: number };\n  throughput: { average: number };\n};\n\nexport const runBenchmark = (url: string) => {\n  return new Promise<WrkResult>((resolve, reject) => {\n    const cmd = `wrk -t${connections} -c${connections} -d${duration}s -H \"Connection: keep-alive\" ${url}`;\n\n    exec(cmd, (err, stdout) => {\n      if (err) {\n        reject(err);\n        return;\n      }\n\n      const output = stdout.toString();\n\n      const reqMatch = output.match(/Requests\\/sec:\\s*([\\d.]+)/);\n      const requests = reqMatch ? parseFloat(reqMatch[1]) : 0;\n\n      const latMatch = output.match(/Latency\\s+([\\d.]+)(ms|s|us)/);\n      let latency = 0;\n      if (latMatch) {\n        const v = parseFloat(latMatch[1]);\n        const unit = latMatch[2];\n        if (unit === \"s\") latency = v * 1000;\n        else if (unit === \"us\") latency = v / 1000;\n        else latency = v;\n      }\n\n      const tpMatch = output.match(/Transfer\\/sec:\\s*([\\d.]+)(KB|MB|B)/);\n      let throughput = 0;\n      if (tpMatch) {\n        const v = parseFloat(tpMatch[1]);\n        const unit = tpMatch[2];\n        if (unit === \"MB\") throughput = v * 1024 * 1024;\n        else if (unit === \"KB\") throughput = v * 1024;\n        else throughput = v;\n      }\n\n      resolve({\n        requests: { average: requests },\n        latency: { average: latency },\n        throughput: { average: throughput },\n      });\n    });\n  });\n};\n"
  },
  {
    "path": "bench/utils/wait.ts",
    "content": "import net from \"node:net\";\n\nexport function waitForServerReady(port: number, retries = 50): Promise<void> {\n  return new Promise((resolve, reject) => {\n    (function check(retries: number) {\n      const socket = net.createConnection(port, \"localhost\");\n\n      socket.on(\"connect\", () => {\n        socket.end();\n        resolve();\n      });\n\n      socket.on(\"error\", () => {\n        if (retries <= 0) return reject(new Error(\"Server not ready\"));\n        setTimeout(() => check(--retries), 50);\n      });\n    })(retries);\n  });\n}\n"
  },
  {
    "path": "biome.json",
    "content": "{\n  \"$schema\": \"https://biomejs.dev/schemas/2.2.3/schema.json\",\n  \"vcs\": {\n    \"enabled\": false,\n    \"clientKind\": \"git\",\n    \"useIgnoreFile\": false\n  },\n  \"files\": {\n    \"ignoreUnknown\": false,\n    \"includes\": [\"**\", \"packages/**\", \"examples/**\", \"bench/**\"]\n  },\n  \"formatter\": {\n    \"enabled\": true,\n    \"indentStyle\": \"space\"\n  },\n  \"linter\": {\n    \"enabled\": true,\n    \"rules\": {\n      \"recommended\": true\n    }\n  },\n  \"javascript\": {\n    \"formatter\": {\n      \"quoteStyle\": \"double\"\n    }\n  },\n  \"assist\": {\n    \"enabled\": true,\n    \"actions\": {\n      \"source\": {\n        \"organizeImports\": \"on\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "cli/.gitignore",
    "content": "bin/\ndist/"
  },
  {
    "path": "cli/Cargo.toml",
    "content": "[package]\nname = \"kito\"                                  # cli\nversion = \"0.1.0\"\nedition = \"2024\"\nauthors = [\"Nehuén <github.com/nehu3n>\"]\ndescription = \"🐺 Kito's official CLI.\"\nlicense = \"MIT\"\nrepository = \"https://github.com/kitojs/kito\"\nreadme = \"readme.md\"\ninclude = [\"src/*\", \"Cargo.toml\", \"readme.md\"]\n\n[[bin]]\nname = \"kito\"\npath = \"src/main.rs\"\n\n[profile.release]\nopt-level = \"z\"\nlto = true\ncodegen-units = 1\npanic = \"abort\"\nstrip = true\n\n[dependencies]\nasync-trait = \"0.1.89\"\nclap = { version = \"4.5.47\", features = [\"derive\"] }\npaste = \"1.0.15\"\ntokio = { version = \"1.47.1\", features = [\"full\"] }\n"
  },
  {
    "path": "cli/install.js",
    "content": ""
  },
  {
    "path": "cli/package.json",
    "content": "{\n  \"name\": \"@kitojs/cli\",\n  \"version\": \"1.0.0\",\n  \"description\": \"🍄 Kito's official CLI.\",\n  \"bin\": {\n    \"kito\": \"bin/kito\"\n  },\n\n  \"scripts\": {\n    \"postinstall\": \"node install.js\"\n  },\n\n  \"keywords\": [],\n\n  \"homepage\": \"https://github.com/kitojs/kito\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/kitojs/kito.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/kitojs/kito/issues\"\n  },\n\n  \"license\": \"MIT\",\n  \"author\": \"Nehuén <github.com/nehu3n>\",\n\n  \"main\": \"bin/kito\",\n\n  \"os\": [\n    \"darwin\",\n    \"linux\",\n    \"win32\"\n  ],\n  \"cpu\": [\n    \"x64\",\n    \"arm64\"\n  ],\n\n  \"files\": [\n    \"bin/\",\n    \"install.js\",\n    \"readme.md\"\n  ]\n}\n"
  },
  {
    "path": "cli/src/commands.rs",
    "content": "use crate::register_commands;\n\nuse async_trait::async_trait;\n\n#[async_trait]\npub(crate) trait Command {\n    async fn run(&self) -> Result<(), ()>;\n}\n\nregister_commands!();\n"
  },
  {
    "path": "cli/src/main.rs",
    "content": "mod commands;\nmod utils;\n\nuse async_trait::async_trait;\nuse clap::{Parser, Subcommand};\n\nuse crate::commands::Command;\n\n#[derive(Parser)]\n#[command(\n    name = \"kito\",\n    version = env!(\"CARGO_PKG_VERSION\"),\n    about = env!(\"CARGO_PKG_DESCRIPTION\")\n)]\n#[command(arg_required_else_help = true)]\nstruct Cli {\n    #[command(subcommand)]\n    command: Option<Commands>,\n}\n\n#[derive(Subcommand)]\nenum Commands {}\n\n#[async_trait]\nimpl Command for Commands {\n    async fn run(&self) -> Result<(), ()> {\n        // match self {}\n\n        Ok(())\n    }\n}\n\n#[tokio::main]\nasync fn main() {\n    let cli = Cli::parse();\n\n    if let Some(cmd) = cli.command {\n        let cmd_run = cmd.run().await;\n        if cmd_run.is_err() {\n            std::process::exit(1);\n        }\n    }\n}\n"
  },
  {
    "path": "cli/src/utils.rs",
    "content": "#[macro_export]\nmacro_rules! register_commands {\n    ($($name:ident),*) => {\n        $(\n            pub(crate) mod $name;\n            paste::paste! {\n                pub(crate) use $name::[<$name:camel Command>];\n            }\n        )*\n    }\n}\n"
  },
  {
    "path": "cliff.toml",
    "content": "[changelog]\nbody = \"\"\"\n{% if version %}\\\n## [{{ version | trim_start_matches(pat=\"v\") }}] - {{ timestamp | date(format=\"%Y-%m-%d\") }}\n{% else %}\\\n## [unreleased]\n{% endif %}\\\n{% for group, commits in commits | group_by(attribute=\"group\") %}\n### {{ group | striptags | trim | upper_first }}\n{% for commit in commits %}\n- {% if commit.scope %}*({{ commit.scope }})* {% endif %}{% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\n{% endfor %}\n{% endfor %}\n\"\"\"\ntrim = true\nrender_always = true\npostprocessors = [\n    { pattern = '<REPO>', replace = \"https://github.com/kitojs/kito\" },\n]\n\n[git]\nconventional_commits = true\nfilter_unconventional = true\nrequire_conventional = false\nsplit_commits = false\ncommit_preprocessors = [\n    { pattern = '\\\\((\\\\w+\\\\s)?#([0-9]+)\\\\)', replace = \"([#${2}](<REPO>/issues/${2}))\" },\n    { pattern = '.*', replace_command = 'typos --write-changes -' },\n]\nprotect_breaking_commits = false\n\ncommit_parsers = [\n    { message = \"^feat\", group = \"<!-- 0 -->🚀 Features\" },\n    { message = \"^fix\", group = \"<!-- 1 -->🐛 Bug Fixes\" },\n    { message = \"^perf\", group = \"<!-- 4 -->⚡ Performance\" },\n    { message = \"^refactor\", group = \"<!-- 2 -->🚜 Refactor\" },\n    { message = \"^style\", group = \"<!-- 5 -->🎨 Styling\" },\n    { message = \"^test\", group = \"<!-- 6 -->🧪 Testing\" },\n    { message = \"^doc\", group = \"<!-- 3 -->📚 Documentation\" },\n    { message = \"^chore\\\\(release\\\\): prepare for\", skip = true },\n    { message = \"^chore\\\\(deps.*\\\\)\", skip = true },\n    { message = \"^chore\\\\(pr\\\\)\", skip = true },\n    { message = \"^chore\\\\(pull\\\\)\", skip = true },\n    { message = \"^chore|^ci\", group = \"<!-- 7 -->⚙️ Miscellaneous Tasks\" },\n    { body = \".*security\", group = \"<!-- 8 -->🛡️ Security\" },\n    { message = \"^revert\", group = \"<!-- 9 -->◀️ Revert\" },\n    { message = \".*\", group = \"<!-- 10 -->💼 Other\" },\n]\n\nfilter_commits = false\nlink_parsers = []\n\nuse_branch_tags = false\ntopo_order = false\ntopo_order_commits = true\nsort_commits = \"oldest\"\nrecurse_submodules = false"
  },
  {
    "path": "examples/fluent/basic.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/clustering/index.ts",
    "content": "import cluster from \"node:cluster\";\nimport { availableParallelism } from \"node:os\";\n\nif (cluster.isPrimary) {\n  const numCPUs = availableParallelism();\n\n  console.log(`Primary ${process.pid} is running`);\n  console.log(`Starting ${numCPUs} workers...`);\n\n  for (let i = 0; i < numCPUs; i++) cluster.fork();\n} else {\n  import(\"./server\");\n}\n"
  },
  {
    "path": "examples/fluent/clustering/server.ts",
    "content": "import { server } from \"kitojs\";\n\nserver({\n  reusePort: true, // this is required for clustering\n})\n  .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n  .listen(3000, () => {\n    console.log(`Worker ${process.pid} listening on port 3000`);\n  });\n"
  },
  {
    "path": "examples/fluent/extend.ts",
    "content": "import { server } from \"kitojs\";\n\ninterface Extends {\n  user: { id: string; name: string };\n}\n\nserver()\n  .extend<Extends>((ctx) => {\n    ctx.user = { id: \"1\", name: \"Neo\" };\n  })\n  .get(\"/\", ({ res, user }) => {\n    res.json({ user });\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/file.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/download\", ({ res }) => {\n    res.sendFile(\"public/banner.png\", {\n      root: \"./\",\n      maxAge: 3600,\n      lastModified: true,\n      cacheControl: true,\n      immutable: false,\n    });\n  })\n  .get(\"/export\", ({ res }) => {\n    res.download(\"public/banner.png\", \"kito-banner.png\");\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/middlewares/index.ts",
    "content": "import { server } from \"kitojs\";\n\nimport { auth } from \"./samples/auth\";\nimport { logger } from \"./samples/logger\";\n\nserver()\n  .use(logger)\n  .get(\"/\", auth, ({ res }) => res.send(\"hello world!\"))\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/middlewares/samples/auth.ts",
    "content": "import { middleware } from \"kitojs\";\n\nexport const auth = middleware((ctx, next) => {\n  const { req, res } = ctx;\n  const header = req.headers.authorization;\n\n  if (header && header === \"Bearer secret_token\") {\n    return next();\n  }\n\n  res.status(401).send(\"unauthorized\");\n});\n"
  },
  {
    "path": "examples/fluent/middlewares/samples/logger.ts",
    "content": "import { middleware } from \"kitojs\";\n\nexport const logger = middleware((ctx, next) => {\n  const { method, url } = ctx.req;\n  const date = new Date().toISOString();\n\n  console.log(`[${date}] ${method} ${url}`);\n  return next();\n});\n"
  },
  {
    "path": "examples/fluent/params.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/:id\", ({ req, res }) => res.send(req.params.id))\n  .get(\"/multi/:id/:name\", ({ req, res }) => {\n    const { id, name } = req.params;\n    res.json({ id, name });\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/route.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .route(\"/\")\n  .get(({ res }) => {\n    res.send(\"hello world!\");\n  })\n  .post(({ req, res }) => {\n    res.json({ body: req.body });\n  })\n  .end()\n  .get(\"/bye\", ({ res }) => {\n    res.send(\"bye!\");\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/router/cats.ts",
    "content": "import { router } from \"kitojs\";\n\nexport default router()\n  .get(\"/\", ({ res }) => {\n    res.send(\"hello cats!\");\n  })\n  .post(\"/\", ({ res }) => {\n    res.json({ msg: \"cat created!\" });\n  });\n"
  },
  {
    "path": "examples/fluent/router/index.ts",
    "content": "import { server } from \"kitojs\";\nimport cats from \"./cats\";\n\nserver()\n  .mount(\"/cats\", cats)\n  .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/schemas/builder.ts",
    "content": "import { schema, server, t } from \"kitojs\";\n\nconst userSchema = schema({\n  params: t.object({ id: t.str().uuid() }),\n  query: t.object({ limit: t.num().max(100) }),\n  body: t.object({ name: t.str().min(1) }),\n});\n\nserver()\n  .post(\n    \"/users:id\",\n    ({ req, res }) => {\n      const { id } = req.params;\n      const { limit } = req.query;\n      const { name } = req.body;\n\n      res.json({ id, limit, name });\n    },\n    userSchema,\n  )\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/schemas/json.ts",
    "content": "import { schema, server } from \"kitojs\";\n\nconst userSchema = schema.json({\n  params: {\n    type: \"object\",\n    properties: {\n      id: { type: \"string\", format: \"uuid\" },\n    },\n    required: [\"id\"],\n  },\n  query: {\n    type: \"object\",\n    properties: {\n      limit: { type: \"number\", maximum: 100 },\n    },\n    required: [\"limit\"],\n  },\n  body: {\n    type: \"object\",\n    properties: {\n      name: { type: \"string\", minLength: 1 },\n    },\n    required: [\"name\"],\n  },\n});\n\nserver()\n  .post(\n    \"/users/:id\",\n    ({ req, res }) => {\n      // types are automatically inferred from userSchema\n      const { id } = req.params;\n      const { limit } = req.query;\n      const { name } = req.body;\n\n      res.json({ id, limit, name });\n    },\n    userSchema,\n  )\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/streaming/sse.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    const sse = res.sse();\n\n    sse.send(\"hello world!\");\n\n    sse.send(\n      {\n        msg: \"this is a message\",\n      },\n      \"message\",\n    );\n\n    sse.close();\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/streaming/stream.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    const stream = res.stream();\n\n    stream.write(\"Chunk 1\\n\");\n\n    setTimeout(() => {\n      stream.write(\"Chunk 2\\n\");\n    }, 1000);\n\n    setTimeout(() => {\n      stream.end(\"Final chunk\\n\");\n    }, 2000);\n  })\n  .listen(3000);\n"
  },
  {
    "path": "examples/fluent/unixSocket.ts",
    "content": "import { server } from \"kitojs\";\n\nserver()\n  .get(\"/\", ({ res }) => {\n    res.send(\"Hello from Unix socket!\");\n  })\n  .listen({ unixSocket: \"./app.sock\" });\n"
  },
  {
    "path": "examples/instance/basic.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"hello world!\");\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/clustering/index.ts",
    "content": "import cluster from \"node:cluster\";\nimport { availableParallelism } from \"node:os\";\n\nif (cluster.isPrimary) {\n  const numCPUs = availableParallelism();\n\n  console.log(`Primary ${process.pid} is running`);\n  console.log(`Starting ${numCPUs} workers...`);\n\n  for (let i = 0; i < numCPUs; i++) cluster.fork();\n} else {\n  import(\"./server\");\n}\n"
  },
  {
    "path": "examples/instance/clustering/server.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server({\n  reusePort: true, // this is required for clustering\n});\n\napp.get(\"/\", ({ res }) => res.send(\"hello world!\"));\n\napp.listen(3000, () => {\n  console.log(`Worker ${process.pid} listening on port 3000`);\n});\n"
  },
  {
    "path": "examples/instance/extend.ts",
    "content": "import { server } from \"kitojs\";\n\ninterface Extends {\n  user: { id: string; name: string };\n}\n\nconst app = server().extend<Extends>((ctx) => {\n  ctx.user = { id: \"1\", name: \"Neo\" };\n});\n\napp.get(\"/\", ({ res, user }) => {\n  res.json({ user });\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/file.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/download\", ({ res }) => {\n  res.sendFile(\"public/banner.png\", {\n    root: \"./\",\n    maxAge: 3600,\n    lastModified: true,\n    cacheControl: true,\n    immutable: false,\n    etag: true,\n  });\n});\n\napp.get(\"/export\", ({ res }) => {\n  res.download(\"public/banner.png\", \"kito-banner.png\");\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/middlewares/index.ts",
    "content": "import { server } from \"kitojs\";\n\nimport { auth } from \"./samples/auth\";\nimport { logger } from \"./samples/logger\";\n\nconst app = server();\napp.use(logger);\n\napp.get(\"/\", auth, ({ res }) => {\n  res.send(\"hello world!\");\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/middlewares/samples/auth.ts",
    "content": "import { middleware } from \"kitojs\";\n\nexport const auth = middleware((ctx, next) => {\n  const { req, res } = ctx;\n  const header = req.headers.authorization;\n\n  if (header && header === \"Bearer secret_token\") {\n    return next();\n  }\n\n  res.status(401).send(\"unauthorized\");\n});\n"
  },
  {
    "path": "examples/instance/middlewares/samples/logger.ts",
    "content": "import { middleware } from \"kitojs\";\n\nexport const logger = middleware((ctx, next) => {\n  const { method, url } = ctx.req;\n  const date = new Date().toISOString();\n\n  console.log(`[${date}] ${method} ${url}`);\n  return next();\n});\n"
  },
  {
    "path": "examples/instance/params.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/:id\", ({ req, res }) => {\n  res.send(req.params.id);\n});\n\napp.get(\"/multi/:id/:name\", ({ req, res }) => {\n  const { id, name } = req.params;\n  res.json({ id, name });\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/route.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\nconst routes = app.route(\"/\");\n\nroutes.get(({ res }) => {\n  res.send(\"hello world!\");\n});\n\nroutes.post(({ req, res }) => {\n  res.json({ body: req.body });\n});\n\napp.get(\"/bye\", ({ res }) => {\n  res.send(\"bye!\");\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/router/cats.ts",
    "content": "import { router } from \"kitojs\";\n\nconst cats = router();\n\ncats.get(\"/\", ({ res }) => {\n  res.send(\"hello cats!\");\n});\n\ncats.post(\"/\", ({ res }) => {\n  res.json({ msg: \"cat created!\" });\n});\n\nexport default cats;\n"
  },
  {
    "path": "examples/instance/router/index.ts",
    "content": "import { server } from \"kitojs\";\nimport cats from \"./cats\";\n\nconst app = server();\napp.mount(\"/cats\", cats);\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"hello world!\");\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/schemas/builder.ts",
    "content": "import { schema, server, t } from \"kitojs\";\n\nconst app = server();\n\nconst userSchema = schema({\n  params: t.object({ id: t.str().uuid() }),\n  query: t.object({ limit: t.num().max(100) }),\n  body: t.object({ name: t.str().min(1) }),\n});\n\napp.post(\n  \"/users/:id\",\n  ({ req, res }) => {\n    // types are automatically inferred from userSchema\n    const { id } = req.params;\n    const { limit } = req.query;\n    const { name } = req.body;\n\n    res.json({ id, limit, name });\n  },\n  userSchema,\n);\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/schemas/json.ts",
    "content": "import { schema, server } from \"kitojs\";\n\nconst app = server();\n\nconst userSchema = schema.json({\n  params: {\n    type: \"object\",\n    properties: {\n      id: { type: \"string\", format: \"uuid\" },\n    },\n    required: [\"id\"],\n  },\n  query: {\n    type: \"object\",\n    properties: {\n      limit: { type: \"number\", maximum: 100 },\n    },\n    required: [\"limit\"],\n  },\n  body: {\n    type: \"object\",\n    properties: {\n      name: { type: \"string\", minLength: 1 },\n    },\n    required: [\"name\"],\n  },\n});\n\napp.post(\n  \"/users/:id\",\n  ({ req, res }) => {\n    // types are automatically inferred from userSchema\n    const { id } = req.params;\n    const { limit } = req.query;\n    const { name } = req.body;\n\n    res.json({ id, limit, name });\n  },\n  userSchema,\n);\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/streaming/sse.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  const sse = res.sse();\n\n  sse.send(\"hello world!\");\n\n  sse.send(\n    {\n      msg: \"this is a message\",\n    },\n    \"message\",\n  );\n\n  sse.close();\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/streaming/stream.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  const stream = res.stream();\n\n  stream.write(\"Chunk 1\\n\");\n\n  setTimeout(() => {\n    stream.write(\"Chunk 2\\n\");\n  }, 1000);\n\n  setTimeout(() => {\n    stream.end(\"Final chunk\\n\");\n  }, 2000);\n});\n\napp.listen(3000);\n"
  },
  {
    "path": "examples/instance/unixSocket.ts",
    "content": "import { server } from \"kitojs\";\n\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"Hello from Unix socket!\");\n});\n\napp.listen({ unixSocket: \"./app.sock\" });\n"
  },
  {
    "path": "examples/package.json",
    "content": "{\n  \"name\": \"@kitojs/examples\",\n  \"description\": \"Kito's usage examples.\",\n  \"private\": true,\n  \"type\": \"module\",\n\n  \"scripts\": {\n    \"ex:run\": \"tsx runExample.ts\"\n  },\n\n  \"dependencies\": {\n    \"kitojs\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"tsx\": \"^4.20.6\",\n    \"typescript\": \"^5.9.2\"\n  }\n}\n"
  },
  {
    "path": "examples/runExample.ts",
    "content": "#!/usr/bin/env tsx\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst args = process.argv.slice(2);\nlet style: string | undefined;\nlet example: string | undefined;\n\nfor (let i = 0; i < args.length; i++) {\n  if (args[i] === \"--style\" && i + 1 < args.length) {\n    style = args[i + 1];\n    i++;\n  } else if (args[i] === \"--example\" && i + 1 < args.length) {\n    example = args[i + 1];\n    i++;\n  }\n}\n\nif (!style || !example) {\n  console.error(\n    \"Usage: pnpm ex:run --style <fluent|instance> --example <example-name>\",\n  );\n  console.error(\"\\nExamples:\");\n  console.error(\"  pnpm ex:run --style fluent --example basic\");\n  console.error(\"  pnpm ex:run --style fluent --example router\");\n  console.error(\"  pnpm ex:run --style fluent --example schemas/builder\");\n  process.exit(1);\n}\n\nif (style !== \"fluent\" && style !== \"instance\") {\n  console.error(`Invalid style: ${style}. Must be 'fluent' or 'instance'.`);\n  process.exit(1);\n}\n\nlet filePath: string;\n\nconst dirWithIndex = resolve(__dirname, style, example, \"index.ts\");\nif (existsSync(dirWithIndex)) {\n  filePath = dirWithIndex;\n} else {\n  const directFile = resolve(__dirname, style, `${example}.ts`);\n  if (existsSync(directFile)) {\n    filePath = directFile;\n  } else {\n    console.error(`Example not found: ${style}/${example}`);\n    console.error(`Tried: ${dirWithIndex} and ${directFile}`);\n    process.exit(1);\n  }\n}\n\nconsole.log(`Running example: ${style}/${example}`);\nimport(filePath);\n"
  },
  {
    "path": "examples/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {},\n  \"include\": [\"instance/**/*\", \"fluent/**/*\"],\n  \"references\": [\n    {\n      \"path\": \"../packages/kitojs\"\n    }\n  ]\n}\n"
  },
  {
    "path": "lefthook.yml",
    "content": "skip_output:\n  - meta\n  - summary\n\npre-commit:\n  parallel: true\n  commands:\n    # Rust commands\n    fmt-check:\n      tags: rust formatter\n      run: cargo fmt --all -- --check\n      fail_text: \"Code is not formatted. Run 'cargo fmt' to fix.\"\n\n    clippy:\n      tags: rust linter\n      run: cargo clippy --all-targets --all-features -- -D warnings\n      fail_text: \"Linting failed. Fix clippy warnings.\"\n\n    check:\n      tags: rust compile\n      run: cargo check --all-targets --all-features\n      fail_text: \"Code doesn't compile. Fix compilation errors.\"\n\n    # TypeScript commands\n    biome-check:\n      tags: js formatter linter\n      glob: \"*.{js,ts,tsx,json,jsonc}\"\n      run: pnpm biome check --write {staged_files}\n      stage_fixed: true\n      fail_text: \"JS/TS formatting/linting failed. Fix biome issues.\"\n\n    \n    # ts-typecheck:\n      # tags: typescript checker\n      # glob: \"*.{ts,tsx}\"\n      # run: pnpm tsc --noEmit\n      # fail_text: \"TypeScript type checking failed. Fix type errors.\"\n\npre-push:\n  parallel: false\n  commands:\n    # Rust tests\n    test:\n      tags: rust test\n      run: cargo test --all-features\n      fail_text: \"Rust tests failed. Fix failing tests before pushing.\"\n\n    # Security audits\n    audit:\n      tags: rust security\n      run: cargo audit\n      fail_text: \"Security vulnerabilities found. Run 'cargo audit fix' or update dependencies.\"\n      skip:\n        - merge\n        - rebase\n\n    npm-audit:\n      tags: npm security\n      run: pnpm audit --audit-level moderate\n      fail_text: \"NPM security vulnerabilities found. Run 'pnpm audit --fix'.\"\n      skip:\n        - merge\n        - rebase\n\nprepare-commit-msg:\n  commands:\n    conventional-commits-prepare:\n      tags: commit-msg\n      run: |\n        # This hook runs before the commit message is created\n        # We can use it to prepare or validate the template\n        echo \"📝 Preparing commit message validation...\"\n        echo \"Remember to use Conventional Commits format: <type>[optional scope]: <description>\"\n\ncommit-msg:\n  commands:\n    conventional-commits:\n      tags: commit-msg\n      run: |\n        #!/bin/sh\n\n        # Try to extract commit message\n        commit_msg=\"\"\n\n        # 1. Argument (standard for commit-msg hook)\n        if [ -n \"$1\" ] && [ -f \"$1\" ]; then\n          commit_msg=\"$(head -n 1 \"$1\" | tr -d '\\r\\n')\"\n        fi\n\n        # 2. Lefthook-provided variable\n        if [ -z \"$commit_msg\" ] && [ -n \"$LEFTHOOK_COMMIT_MSG\" ]; then\n          commit_msg=\"$(echo \"$LEFTHOOK_COMMIT_MSG\" | head -n 1 | tr -d '\\r\\n')\"\n        fi\n\n        # 3. Git fallback\n        if [ -z \"$commit_msg\" ] && [ -f \".git/COMMIT_EDITMSG\" ]; then\n          commit_msg=\"$(head -n 1 .git/COMMIT_EDITMSG | tr -d '\\r\\n')\"\n        fi\n\n        # Skip empty or comment-only messages\n        if [ -z \"$commit_msg\" ] || echo \"$commit_msg\" | grep -qE '^#'; then\n          echo \"⚠️  Empty commit message or comment, skipping validation.\"\n          exit 0\n        fi\n\n        echo \"🔍 Validating commit message: \\\"$commit_msg\\\"\"\n\n        # Check Conventional Commit pattern\n        if ! echo \"$commit_msg\" | grep -qE '^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([^)]+\\))?: .{1,50}$'; then\n          echo \"❌ Invalid commit message format!\"\n          echo \"Format: <type>[optional scope]: <description>\"\n          echo \"Types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test\"\n          echo \"Example: feat(auth): add login functionality\"\n          echo \"Your message: \\\"$commit_msg\\\"\"\n          exit 1\n        fi\n\n        # Length check\n        if [ \"${#commit_msg}\" -gt 72 ]; then\n          echo \"❌ Commit message too long! Keep it under 72 characters.\"\n          echo \"Length: ${#commit_msg}\"\n          echo \"Your message: \\\"$commit_msg\\\"\"\n          exit 1\n        fi\n\n        # Imperative mood check\n        description=\"$(echo \"$commit_msg\" | sed -E 's/^[a-z]+(\\([^)]+\\))?: //')\"\n        if echo \"$description\" | grep -qE '^(added|fixed|updated|changed|removed|created)'; then\n          echo \"⚠️  Use imperative mood (add, fix, update), not past tense\"\n          echo \"Example: 'feat: add auth' not 'feat: added auth'\"\n          echo \"Your message: \\\"$commit_msg\\\"\"\n          exit 1\n        fi\n\n        echo \"✅ Commit message is valid!\"\n      fail_text: \"Commit message doesn't follow Conventional Commits specification.\"\n\npost-checkout:\n  commands:\n    cargo-update:\n      tags: rust dependencies\n      files: git diff --name-only HEAD@{1} HEAD\n      glob: \"{Cargo.toml,Cargo.lock}\"\n      run: |\n        echo \"🔄 Cargo files changed, updating dependencies...\"\n        cargo check\n      skip:\n        - merge\n        - rebase\n\n    npm-install:\n      tags: npm dependencies\n      files: git diff --name-only HEAD@{1} HEAD\n      glob: \"{package.json,pnpm-lock.yaml,pnpm-workspace.yaml}\"\n      run: |\n        echo \"🔄 NPM files changed, updating dependencies...\"\n        pnpm install\n      skip:\n        - merge\n        - rebase\n\npost-merge:\n  commands:\n    cargo-check:\n      tags: rust post-merge\n      run: |\n        echo \"🔄 Running cargo check after merge...\"\n        cargo check\n        echo \"✅ Rust dependencies updated successfully\"\n\n    npm-check:\n      tags: npm post-merge\n      run: |\n        echo \"🔄 Running npm check after merge...\"\n        pnpm install --frozen-lockfile\n        echo \"✅ NPM dependencies updated successfully\"\n\ncolors: true\nno_tty: false\nsource_dir: \".lefthook\"\nsource_dir_local: \".lefthook-local\"\n\noutput:\n  - execution\n  - execution_out\n  - execution_info\n  - skips"
  },
  {
    "path": "license",
    "content": "MIT License\n\nCopyright (c) 2024 kitojs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"kito\",\n  \"version\": \"1.0.0\",\n  \"description\": \"The Kito's workspace.\",\n  \"scripts\": {\n    \"fmt\": \"biome format\",\n    \"fmt:fix\": \"biome format --write\",\n    \"lint\": \"biome lint\",\n    \"lint:fix\": \"biome lint --write\",\n    \"check\": \"biome check\",\n    \"check:fix\": \"biome check --write\",\n\n    \"build\": \"pnpm core:build --platform && pnpm ts:build\",\n    \"core:build\": \"pnpm --filter @kitojs/kito-core build\",\n    \"ts:build\": \"pnpm --filter @kitojs/types build && pnpm --filter kitojs build\",\n\n    \"dev\": \"pnpm -r dev\",\n    \"test\": \"pnpm -r test\",\n\n    \"ex:run\": \"pnpm --filter examples ex:run\",\n    \"bench:run\": \"pnpm --filter bench bench:run\"\n  },\n  \"author\": \"Nehuén <github.com/nehu3n>\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@biomejs/biome\": \"2.2.3\",\n    \"@types/node\": \"^24.5.2\",\n    \"typescript\": \"^5.9.2\"\n  }\n}\n"
  },
  {
    "path": "packages/core/.gitignore",
    "content": "dist/"
  },
  {
    "path": "packages/core/Cargo.toml",
    "content": "[package]\nname = \"core\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[lib]\nname = \"core\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nnapi = { version = \"3.2.4\", default-features = false, features = [\"async\"] }\nnapi-derive = \"3.2.4\"\nhyper = { version = \"1\", features = [\"full\"] }\ntokio = { version = \"1\", features = [\"full\"] }\nhttp-body-util = \"0.1\"\nhyper-util = { version = \"0.1\", features = [\"full\"] }\nonce_cell = \"1.21.3\"\ndashmap = \"6.1.0\"\nurlencoding = \"2.1.3\"\nhttpdate = \"1.0.3\"\nparking_lot = \"0.12.5\"\nserde = { version = \"1.0.228\", features = [\"derive\"] }\nregex = \"1.12.2\"\nserde_json = \"1.0.145\"\nmatchit = \"0.9.0\"\nahash = \"0.8.12\"\nbase64 = \"0.22.1\"\nsocket2 = \"0.6.1\"\nfutures-util = \"0.3.31\"\n\n[dev-dependencies]\ntokio-test = \"0.4.4\"\n\n[build-dependencies]\nnapi-build = \"2.2.3\"\n"
  },
  {
    "path": "packages/core/build.rs",
    "content": "fn main() {\n    napi_build::setup();\n}\n"
  },
  {
    "path": "packages/core/package.json",
    "content": "{\n  \"name\": \"@kitojs/kito-core\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"Internal logic (core) of the Kito framework written in Rust.\",\n  \"scripts\": {\n    \"build\": \"napi build --release --esm --const-enum --output-dir dist\",\n    \"test\": \"cargo test\"\n  },\n\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"@napi-rs/cli\": \"^3.1.5\"\n  },\n\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.js\",\n      \"types\": \"./dist/index.d.ts\"\n    }\n  },\n  \"files\": [\n    \"dist\"\n  ],\n\n  \"napi\": {\n    \"binaryName\": \"core\",\n    \"packageName\": \"@kitojs/kito-core\",\n    \"targets\": [\n      \"x86_64-apple-darwin\",\n      \"aarch64-apple-darwin\",\n      \"x86_64-unknown-linux-gnu\",\n      \"x86_64-pc-windows-msvc\",\n      \"x86_64-unknown-linux-musl\",\n      \"aarch64-unknown-linux-gnu\",\n      \"i686-pc-windows-msvc\",\n      \"armv7-unknown-linux-gnueabihf\",\n      \"aarch64-linux-android\",\n      \"x86_64-unknown-freebsd\",\n      \"aarch64-unknown-linux-musl\",\n      \"aarch64-pc-windows-msvc\",\n      \"armv7-linux-androideabi\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">= 10\"\n  }\n}\n"
  },
  {
    "path": "packages/core/src/http/cookies.rs",
    "content": "#[derive(Clone, Default)]\n#[napi(object)]\npub struct CookieOptionsCore {\n    pub domain: Option<String>,\n    pub http_only: Option<bool>,\n    pub max_age: Option<i32>,\n    pub path: Option<String>,\n    pub secure: Option<bool>,\n    pub signed: Option<bool>,\n    pub same_site: Option<String>,\n}\n\npub fn serialize_cookie(name: &str, value: &str, options: &CookieOptionsCore) -> String {\n    let mut cookie = format!(\"{name}={value}\");\n\n    if let Some(max_age) = options.max_age {\n        cookie.push_str(&format!(\"; Max-Age={max_age}\"));\n    }\n\n    if let Some(ref path) = options.path {\n        cookie.push_str(&format!(\"; Path={path}\"));\n    } else {\n        cookie.push_str(\"; Path=/\");\n    }\n\n    if let Some(ref domain) = options.domain {\n        cookie.push_str(&format!(\"; Domain={domain}\"));\n    }\n\n    if options.http_only.unwrap_or(false) {\n        cookie.push_str(\"; HttpOnly\");\n    }\n\n    if options.secure.unwrap_or(false) {\n        cookie.push_str(\"; Secure\");\n    }\n\n    if let Some(ref same_site) = options.same_site {\n        cookie.push_str(&format!(\"; SameSite={same_site}\"));\n    }\n\n    cookie\n}\n"
  },
  {
    "path": "packages/core/src/http/cookies_tests.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use super::super::cookies::*;\n\n    #[test]\n    fn test_basic_cookie() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: None,\n            max_age: None,\n            path: None,\n            secure: None,\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"session\", \"abc123\", &options);\n        assert!(result.contains(\"session=abc123\"));\n        assert!(result.contains(\"Path=/\"));\n    }\n\n    #[test]\n    fn test_cookie_with_max_age() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: None,\n            max_age: Some(3600),\n            path: None,\n            secure: None,\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"token\", \"xyz\", &options);\n        assert!(result.contains(\"Max-Age=3600\"));\n    }\n\n    #[test]\n    fn test_cookie_with_custom_path() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: None,\n            max_age: None,\n            path: Some(\"/admin\".to_string()),\n            secure: None,\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"admin\", \"secret\", &options);\n        assert!(result.contains(\"Path=/admin\"));\n    }\n\n    #[test]\n    fn test_cookie_with_domain() {\n        let options = CookieOptionsCore {\n            domain: Some(\"example.com\".to_string()),\n            http_only: None,\n            max_age: None,\n            path: None,\n            secure: None,\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"user\", \"john\", &options);\n        assert!(result.contains(\"Domain=example.com\"));\n    }\n\n    #[test]\n    fn test_cookie_http_only() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: Some(true),\n            max_age: None,\n            path: None,\n            secure: None,\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"secure\", \"data\", &options);\n        assert!(result.contains(\"HttpOnly\"));\n    }\n\n    #[test]\n    fn test_cookie_secure() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: None,\n            max_age: None,\n            path: None,\n            secure: Some(true),\n            signed: None,\n            same_site: None,\n        };\n\n        let result = serialize_cookie(\"token\", \"value\", &options);\n        assert!(result.contains(\"Secure\"));\n    }\n\n    #[test]\n    fn test_cookie_same_site() {\n        let options = CookieOptionsCore {\n            domain: None,\n            http_only: None,\n            max_age: None,\n            path: None,\n            secure: None,\n            signed: None,\n            same_site: Some(\"Strict\".to_string()),\n        };\n\n        let result = serialize_cookie(\"csrf\", \"token\", &options);\n        assert!(result.contains(\"SameSite=Strict\"));\n    }\n\n    #[test]\n    fn test_cookie_all_options() {\n        let options = CookieOptionsCore {\n            domain: Some(\"example.com\".to_string()),\n            http_only: Some(true),\n            max_age: Some(7200),\n            path: Some(\"/api\".to_string()),\n            secure: Some(true),\n            signed: None,\n            same_site: Some(\"Lax\".to_string()),\n        };\n\n        let result = serialize_cookie(\"full\", \"options\", &options);\n\n        assert!(result.contains(\"full=options\"));\n        assert!(result.contains(\"Max-Age=7200\"));\n        assert!(result.contains(\"Path=/api\"));\n        assert!(result.contains(\"Domain=example.com\"));\n        assert!(result.contains(\"HttpOnly\"));\n        assert!(result.contains(\"Secure\"));\n        assert!(result.contains(\"SameSite=Lax\"));\n    }\n}\n"
  },
  {
    "path": "packages/core/src/http/files.rs",
    "content": "use hyper::body::Bytes;\n\nuse std::{collections::HashMap, time::UNIX_EPOCH};\nuse tokio::{fs::File, io::AsyncReadExt};\n\nuse crate::http::mime::get_mime_type;\nuse crate::http::response::SendFileOptionsCore;\n\npub async fn read_file_for_response(\n    path: &str,\n    options: Option<SendFileOptionsCore>,\n) -> Result<(Bytes, HashMap<String, String>), std::io::Error> {\n    let full_path = if let Some(ref opts) = options {\n        if let Some(ref root) = opts.root { format!(\"{root}/{path}\") } else { path.to_string() }\n    } else {\n        path.to_string()\n    };\n\n    let mut file = File::open(&full_path).await?;\n    let metadata = file.metadata().await?;\n    let mut contents = Vec::new();\n    file.read_to_end(&mut contents).await?;\n\n    let mut headers = HashMap::new();\n    headers.insert(\"Content-Type\".to_string(), get_mime_type(path).to_string());\n    headers.insert(\"Content-Length\".to_string(), metadata.len().to_string());\n\n    if let Some(opts) = options {\n        if let Some(ref custom_headers) = opts.headers {\n            headers.extend(custom_headers.clone());\n        }\n\n        if opts.last_modified.unwrap_or(true)\n            && let Ok(modified) = metadata.modified()\n            && let Ok(duration) = modified.duration_since(UNIX_EPOCH)\n        {\n            headers.insert(\n                \"Last-Modified\".to_string(),\n                httpdate::fmt_http_date(UNIX_EPOCH + duration),\n            );\n        }\n\n        if opts.cache_control.unwrap_or(true)\n            && let Some(max_age) = opts.max_age\n        {\n            let cache_value = if opts.immutable.unwrap_or(false) {\n                format!(\"public, max-age={max_age}, immutable\")\n            } else {\n                format!(\"public, max-age={max_age}\")\n            };\n            headers.insert(\"Cache-Control\".to_string(), cache_value);\n        }\n\n        if opts.accept_ranges.unwrap_or(true) {\n            headers.insert(\"Accept-Ranges\".to_string(), \"bytes\".to_string());\n        }\n    }\n\n    Ok((Bytes::from(contents), headers))\n}\n"
  },
  {
    "path": "packages/core/src/http/mime.rs",
    "content": "use std::path::Path;\n\npub fn get_mime_type(path: &str) -> &'static str {\n    let extension = Path::new(path).extension().and_then(|e| e.to_str()).unwrap_or(\"\");\n\n    match extension.to_lowercase().as_str() {\n        \"html\" | \"htm\" => \"text/html\",\n        \"css\" => \"text/css\",\n        \"js\" | \"mjs\" => \"application/javascript\",\n        \"json\" => \"application/json\",\n        \"xml\" => \"application/xml\",\n        \"txt\" => \"text/plain\",\n        \"png\" => \"image/png\",\n        \"jpg\" | \"jpeg\" => \"image/jpeg\",\n        \"gif\" => \"image/gif\",\n        \"svg\" => \"image/svg+xml\",\n        \"webp\" => \"image/webp\",\n        \"ico\" => \"image/x-icon\",\n        \"pdf\" => \"application/pdf\",\n        \"zip\" => \"application/zip\",\n        \"wasm\" => \"application/wasm\",\n        \"mp4\" => \"video/mp4\",\n        \"webm\" => \"video/webm\",\n        \"mp3\" => \"audio/mpeg\",\n        \"wav\" => \"audio/wav\",\n        \"woff\" | \"woff2\" => \"font/woff2\",\n        \"ttf\" => \"font/ttf\",\n        \"otf\" => \"font/otf\",\n        _ => \"application/octet-stream\",\n    }\n}\n"
  },
  {
    "path": "packages/core/src/http/mime_tests.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use super::super::mime::get_mime_type;\n\n    #[test]\n    fn test_html_mime_types() {\n        assert_eq!(get_mime_type(\"index.html\"), \"text/html\");\n        assert_eq!(get_mime_type(\"page.htm\"), \"text/html\");\n    }\n\n    #[test]\n    fn test_css_mime_type() {\n        assert_eq!(get_mime_type(\"styles.css\"), \"text/css\");\n    }\n\n    #[test]\n    fn test_javascript_mime_types() {\n        assert_eq!(get_mime_type(\"app.js\"), \"application/javascript\");\n        assert_eq!(get_mime_type(\"module.mjs\"), \"application/javascript\");\n    }\n\n    #[test]\n    fn test_json_mime_type() {\n        assert_eq!(get_mime_type(\"data.json\"), \"application/json\");\n    }\n\n    #[test]\n    fn test_image_mime_types() {\n        assert_eq!(get_mime_type(\"photo.png\"), \"image/png\");\n        assert_eq!(get_mime_type(\"photo.jpg\"), \"image/jpeg\");\n        assert_eq!(get_mime_type(\"photo.jpeg\"), \"image/jpeg\");\n        assert_eq!(get_mime_type(\"icon.gif\"), \"image/gif\");\n        assert_eq!(get_mime_type(\"logo.svg\"), \"image/svg+xml\");\n        assert_eq!(get_mime_type(\"image.webp\"), \"image/webp\");\n    }\n\n    #[test]\n    fn test_font_mime_types() {\n        assert_eq!(get_mime_type(\"font.woff\"), \"font/woff2\");\n        assert_eq!(get_mime_type(\"font.woff2\"), \"font/woff2\");\n        assert_eq!(get_mime_type(\"font.ttf\"), \"font/ttf\");\n        assert_eq!(get_mime_type(\"font.otf\"), \"font/otf\");\n    }\n\n    #[test]\n    fn test_video_mime_types() {\n        assert_eq!(get_mime_type(\"video.mp4\"), \"video/mp4\");\n        assert_eq!(get_mime_type(\"video.webm\"), \"video/webm\");\n    }\n\n    #[test]\n    fn test_audio_mime_types() {\n        assert_eq!(get_mime_type(\"song.mp3\"), \"audio/mpeg\");\n        assert_eq!(get_mime_type(\"sound.wav\"), \"audio/wav\");\n    }\n\n    #[test]\n    fn test_default_mime_type() {\n        assert_eq!(get_mime_type(\"file.unknown\"), \"application/octet-stream\");\n        assert_eq!(get_mime_type(\"no_extension\"), \"application/octet-stream\");\n    }\n\n    #[test]\n    fn test_case_insensitive() {\n        assert_eq!(get_mime_type(\"FILE.HTML\"), \"text/html\");\n        assert_eq!(get_mime_type(\"IMAGE.PNG\"), \"image/png\");\n        assert_eq!(get_mime_type(\"Script.JS\"), \"application/javascript\");\n    }\n\n    #[test]\n    fn test_path_with_directories() {\n        assert_eq!(get_mime_type(\"/path/to/file.html\"), \"text/html\");\n        assert_eq!(get_mime_type(\"../assets/image.png\"), \"image/png\");\n    }\n}\n"
  },
  {
    "path": "packages/core/src/http/request.rs",
    "content": "use http_body_util::BodyExt;\nuse hyper::{\n    Request,\n    body::{Bytes, Incoming},\n};\n\nuse napi::bindgen_prelude::{Buffer, External};\n\nuse std::{collections::HashMap, net::SocketAddr, sync::Arc};\n\n#[derive(Clone)]\npub struct RequestCore {\n    pub method: String,\n    pub url: String,\n    pub pathname: String,\n    pub search: Option<String>,\n    pub protocol: String,\n    pub hostname: String,\n    pub original_url: String,\n    pub secure: bool,\n    pub xhr: bool,\n    pub ip: String,\n    pub ips: Vec<String>,\n\n    pub body: Bytes,\n    pub headers_raw: HashMap<String, String>,\n    pub params: HashMap<String, String>,\n    pub query_raw: HashMap<String, Vec<String>>,\n    pub cookies_raw: HashMap<String, String>,\n}\n\nimpl RequestCore {\n    pub async fn new(\n        req: Request<Incoming>,\n        remote_addr: Option<SocketAddr>,\n        trust_proxy: bool,\n    ) -> Result<Self, Box<dyn std::error::Error>> {\n        let method = req.method().as_str().to_string();\n        let uri = req.uri();\n        let url = uri.to_string();\n        let pathname = uri.path().to_string();\n        let search = uri.query().map(|q| format!(\"?{q}\"));\n        let original_url = url.clone();\n\n        let mut headers_raw = HashMap::with_capacity(req.headers().len());\n        for (name, value) in req.headers() {\n            if let Ok(v) = value.to_str() {\n                headers_raw.insert(name.as_str().to_string(), v.to_string());\n            }\n        }\n\n        let mut query_raw: HashMap<String, Vec<String>> = HashMap::new();\n        if let Some(q) = uri.query() {\n            for pair in q.split('&') {\n                if let Some((key, value)) = pair.split_once('=') {\n                    let decoded_key = urlencoding::decode(key).unwrap_or_default().into_owned();\n                    let decoded_value = urlencoding::decode(value).unwrap_or_default().into_owned();\n                    query_raw.entry(decoded_key).or_default().push(decoded_value);\n                }\n            }\n        }\n\n        let scheme = req.uri().scheme_str().unwrap_or(\"http\").to_string();\n\n        let body = req.into_body().collect().await?.to_bytes();\n\n        let protocol = if trust_proxy {\n            headers_raw\n                .get(\"x-forwarded-proto\")\n                .map(|s| s.to_string())\n                .unwrap_or_else(|| \"http\".to_string())\n        } else {\n            scheme\n        };\n\n        let secure = protocol.eq_ignore_ascii_case(\"https\");\n        let hostname = headers_raw.get(\"host\").cloned().unwrap_or_else(|| \"localhost\".to_string());\n\n        let cookies_raw = headers_raw.get(\"cookie\").map_or(HashMap::new(), |cookie_str| {\n            cookie_str\n                .split(';')\n                .filter_map(|c| {\n                    let parts: Vec<&str> = c.trim().splitn(2, '=').collect();\n                    if parts.len() == 2 {\n                        Some((parts[0].to_string(), parts[1].to_string()))\n                    } else {\n                        None\n                    }\n                })\n                .collect()\n        });\n\n        let ips: Vec<String> = if trust_proxy {\n            headers_raw\n                .get(\"x-forwarded-for\")\n                .map(|s| s.split(',').map(|ip| ip.trim().to_string()).collect())\n                .unwrap_or_default()\n        } else {\n            vec![]\n        };\n\n        let ip = ips\n            .first()\n            .cloned()\n            .or_else(|| remote_addr.map(|a| a.ip().to_string()))\n            .unwrap_or_default();\n\n        let xhr =\n            headers_raw.get(\"x-requested-with\").map(|v| v == \"XMLHttpRequest\").unwrap_or(false);\n\n        Ok(Self {\n            method,\n            url,\n            pathname,\n            search,\n            protocol,\n            hostname,\n            original_url,\n            secure,\n            xhr,\n            ip,\n            ips,\n            body,\n            headers_raw,\n            params: HashMap::new(),\n            query_raw,\n            cookies_raw,\n        })\n    }\n}\n\n#[napi]\npub fn get_body_buffer(core: &External<Arc<RequestCore>>) -> Buffer {\n    Buffer::from(core.body.as_ref())\n}\n\n#[napi]\npub fn get_header(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {\n    core.headers_raw.get(&name.to_lowercase()).cloned()\n}\n\n#[napi]\npub fn get_all_headers(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {\n    core.headers_raw.clone()\n}\n\n#[napi]\npub fn get_query_param(core: &External<Arc<RequestCore>>, name: String) -> Option<Vec<String>> {\n    core.query_raw.get(&name).cloned()\n}\n\n#[napi]\npub fn get_all_query(core: &External<Arc<RequestCore>>) -> HashMap<String, Vec<String>> {\n    core.query_raw.clone()\n}\n\n#[napi]\npub fn get_param(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {\n    core.params.get(&name).cloned()\n}\n\n#[napi]\npub fn get_all_params(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {\n    core.params.clone()\n}\n\n#[napi]\npub fn get_cookie(core: &External<Arc<RequestCore>>, name: String) -> Option<String> {\n    core.cookies_raw.get(&name).cloned()\n}\n\n#[napi]\npub fn get_all_cookies(core: &External<Arc<RequestCore>>) -> HashMap<String, String> {\n    core.cookies_raw.clone()\n}\n\n#[napi]\npub fn get_method(core: &External<Arc<RequestCore>>) -> String {\n    core.method.clone()\n}\n\n#[napi]\npub fn get_url(core: &External<Arc<RequestCore>>) -> String {\n    core.url.clone()\n}\n\n#[napi]\npub fn get_pathname(core: &External<Arc<RequestCore>>) -> String {\n    core.pathname.clone()\n}\n\n#[napi]\npub fn get_search(core: &External<Arc<RequestCore>>) -> Option<String> {\n    core.search.clone()\n}\n\n#[napi]\npub fn get_protocol(core: &External<Arc<RequestCore>>) -> String {\n    core.protocol.clone()\n}\n\n#[napi]\npub fn get_hostname(core: &External<Arc<RequestCore>>) -> String {\n    core.hostname.clone()\n}\n\n#[napi]\npub fn get_ip(core: &External<Arc<RequestCore>>) -> String {\n    core.ip.clone()\n}\n\n#[napi]\npub fn get_ips(core: &External<Arc<RequestCore>>) -> Vec<String> {\n    core.ips.clone()\n}\n\n#[napi]\npub fn get_secure(core: &External<Arc<RequestCore>>) -> bool {\n    core.secure\n}\n\n#[napi]\npub fn get_xhr(core: &External<Arc<RequestCore>>) -> bool {\n    core.xhr\n}\n"
  },
  {
    "path": "packages/core/src/http/response.rs",
    "content": "use http_body_util::{Full, StreamBody, combinators::BoxBody};\nuse hyper::body::{Bytes, Frame};\n\nuse napi::bindgen_prelude::{Buffer, External};\n\nuse parking_lot::Mutex;\nuse serde_json::from_slice;\n\nuse std::{collections::HashMap, sync::Arc};\nuse tokio::sync::mpsc::UnboundedSender;\n\npub struct ResponseChannel {\n    pub tx: Mutex<Option<UnboundedSender<ResponseMessage>>>,\n}\n\nimpl ResponseChannel {\n    pub fn new(tx: UnboundedSender<ResponseMessage>) -> Self {\n        Self { tx: Mutex::new(Some(tx)) }\n    }\n}\n\npub enum ResponseMessage {\n    Complete { status: u16, headers: Vec<(String, String)>, body: Bytes },\n    StreamStart { status: u16, headers: Vec<(String, String)> },\n    StreamChunk { data: Bytes },\n    StreamEnd,\n}\n\npub enum ResponseBody {\n    Full(Full<Bytes>),\n    Stream(StreamBody<Frame<Bytes>>),\n}\n\npub type BoxedBody = BoxBody<Bytes, Box<dyn std::error::Error + Send + Sync>>;\n\n/// buffer: [status_code(2)] [headers_len(4)] [headers_json] [body]\n#[napi]\npub fn send_response(channel: &External<Arc<ResponseChannel>>, buffer: Buffer) -> napi::Result<()> {\n    let data = buffer.as_ref();\n\n    if data.len() < 6 {\n        return Err(napi::Error::from_reason(\"Invalid response buffer\"));\n    }\n\n    let status_code = u16::from_le_bytes([data[0], data[1]]);\n\n    let headers_len = u32::from_le_bytes([data[2], data[3], data[4], data[5]]) as usize;\n\n    if data.len() < 6 + headers_len {\n        return Err(napi::Error::from_reason(\"Invalid headers length\"));\n    }\n\n    let headers_json = &data[6..6 + headers_len];\n    let headers: Vec<(String, String)> = from_slice(headers_json)\n        .map_err(|e| napi::Error::from_reason(format!(\"Invalid headers JSON: {e}\")))?;\n\n    let body_start = 6 + headers_len;\n    let body = if body_start < data.len() {\n        Bytes::copy_from_slice(&data[body_start..])\n    } else {\n        Bytes::new()\n    };\n\n    let mut tx_guard = channel.tx.lock();\n    if let Some(tx) = tx_guard.as_ref() {\n        let _ = tx.send(ResponseMessage::Complete { status: status_code, headers, body });\n        *tx_guard = None;\n        Ok(())\n    } else {\n        Err(napi::Error::from_reason(\"Response already sent\"))\n    }\n}\n\n/// buffer: [status_code(2)] [headers_len(4)] [headers_json]\n#[napi]\npub fn start_stream(channel: &External<Arc<ResponseChannel>>, buffer: Buffer) -> napi::Result<()> {\n    let data = buffer.as_ref();\n\n    if data.len() < 6 {\n        return Err(napi::Error::from_reason(\"Invalid stream start buffer\"));\n    }\n\n    let status_code = u16::from_le_bytes([data[0], data[1]]);\n    let headers_len = u32::from_le_bytes([data[2], data[3], data[4], data[5]]) as usize;\n\n    if data.len() < 6 + headers_len {\n        return Err(napi::Error::from_reason(\"Invalid headers length\"));\n    }\n\n    let headers_json = &data[6..6 + headers_len];\n    let headers: Vec<(String, String)> = from_slice(headers_json)\n        .map_err(|e| napi::Error::from_reason(format!(\"Invalid headers JSON: {e}\")))?;\n\n    let tx_guard = channel.tx.lock();\n    if let Some(tx) = tx_guard.as_ref() {\n        let _ = tx.send(ResponseMessage::StreamStart { status: status_code, headers });\n        Ok(())\n    } else {\n        Err(napi::Error::from_reason(\"Response already sent\"))\n    }\n}\n\n#[napi]\npub fn send_chunk(channel: &External<Arc<ResponseChannel>>, data: Buffer) -> napi::Result<()> {\n    let tx_guard = channel.tx.lock();\n    if let Some(tx) = tx_guard.as_ref() {\n        let bytes = Bytes::copy_from_slice(data.as_ref());\n        let _ = tx.send(ResponseMessage::StreamChunk { data: bytes });\n        Ok(())\n    } else {\n        Err(napi::Error::from_reason(\"Stream not started\"))\n    }\n}\n\n#[napi]\npub fn end_stream(channel: &External<Arc<ResponseChannel>>) -> napi::Result<()> {\n    let mut tx_guard = channel.tx.lock();\n    if let Some(tx) = tx_guard.take() {\n        let _ = tx.send(ResponseMessage::StreamEnd);\n        Ok(())\n    } else {\n        Err(napi::Error::from_reason(\"Stream already ended\"))\n    }\n}\n\n#[derive(Clone)]\n#[napi(object)]\npub struct SendFileOptionsCore {\n    pub max_age: Option<u32>,\n    pub root: Option<String>,\n    pub last_modified: Option<bool>,\n    pub headers: Option<HashMap<String, String>>,\n    pub dotfiles: Option<String>,\n    pub accept_ranges: Option<bool>,\n    pub cache_control: Option<bool>,\n    pub immutable: Option<bool>,\n}\n"
  },
  {
    "path": "packages/core/src/http.rs",
    "content": "pub mod cookies;\npub mod cookies_tests;\npub mod files;\npub mod mime;\npub mod mime_tests;\npub mod request;\npub mod response;\n"
  },
  {
    "path": "packages/core/src/lib.rs",
    "content": "#[macro_use]\nextern crate napi_derive;\n\npub mod http;\npub mod server;\npub mod validation;\n"
  },
  {
    "path": "packages/core/src/server/context.rs",
    "content": "use crate::http::{request::RequestCore, response::ResponseChannel};\nuse napi::{\n    Env,\n    bindgen_prelude::{External, Object, ToNapiValue},\n    sys,\n};\nuse std::sync::Arc;\n\npub struct ContextObject {\n    pub req: External<Arc<RequestCore>>,\n    pub res: External<Arc<ResponseChannel>>,\n}\n\nimpl ToNapiValue for ContextObject {\n    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> napi::Result<sys::napi_value> {\n        let mut obj = Object::new(&Env::from_raw(env))?;\n        obj.set(\"req\", val.req)?;\n        obj.set(\"res\", val.res)?;\n        unsafe { Object::to_napi_value(env, obj) }\n    }\n}\n"
  },
  {
    "path": "packages/core/src/server/core.rs",
    "content": "use hyper::server::conn::http1;\nuse hyper_util::rt::TokioIo;\n\nuse napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};\nuse napi_derive::napi;\n\nuse std::net::SocketAddr;\nuse tokio::{net::TcpListener, sync::watch};\n\n#[cfg(unix)]\nuse std::fs;\n#[cfg(unix)]\nuse std::path::Path;\n#[cfg(unix)]\nuse tokio::net::UnixListener;\n\nuse crate::server::{handler::handle_request, routes::insert_route};\n\nuse super::routes::Route;\n\n#[derive(Clone)]\n#[napi(object)]\npub struct ServerOptionsCore {\n    pub port: Option<u16>,\n    pub host: Option<String>,\n    pub unix_socket: Option<String>,\n    pub trust_proxy: Option<bool>,\n    pub max_request_size: Option<u32>,\n    pub timeout: Option<u32>,\n    pub reuse_port: Option<bool>,\n}\n\n#[napi]\npub struct ServerCore {\n    config: ServerOptionsCore,\n    shutdown_tx: Option<watch::Sender<()>>,\n}\n\n#[napi]\nimpl ServerCore {\n    #[napi(constructor)]\n    pub fn new(config: ServerOptionsCore) -> Self {\n        ServerCore { config, shutdown_tx: None }\n    }\n\n    #[napi]\n    pub fn get_config(&self) -> ServerOptionsCore {\n        self.config.clone()\n    }\n\n    #[napi]\n    pub fn set_config(&mut self, config: ServerOptionsCore) {\n        self.config = config;\n    }\n\n    #[napi]\n    pub fn add_route(&mut self, route: Route) -> napi::Result<()> {\n        insert_route(route)\n    }\n\n    /// Start the HTTP server on TCP or Unix socket and execute the `ready` callback if provided.\n    ///\n    /// # Safety\n    ///\n    /// This function is unsafe because it exposes logic that will be called from JavaScript via N-API, and depends on:\n    /// - The `ServerCore` object remains alive while async tasks are running.\n    /// - The `ThreadsafeFunction` passed (if it exists) is valid and has not been released.\n    /// - `start` is not called twice simultaneously on the same instance.\n    ///\n    /// The caller must guarantee these conditions.\n    #[napi(ts_args_type = \"ready: (() => void) | undefined\")]\n    pub async unsafe fn start(&mut self, ready: Option<ThreadsafeFunction<()>>) {\n        let (shutdown_tx, mut shutdown_rx) = watch::channel::<()>(());\n        self.shutdown_tx = Some(shutdown_tx);\n\n        #[cfg(unix)]\n        if let Some(ref socket_path) = self.config.unix_socket {\n            self.start_unix_socket(socket_path, ready, &mut shutdown_rx).await;\n            return;\n        }\n\n        self.start_tcp(ready, &mut shutdown_rx).await;\n    }\n\n    async fn start_tcp(\n        &self,\n        ready: Option<ThreadsafeFunction<()>>,\n        shutdown_rx: &mut watch::Receiver<()>,\n    ) {\n        let port = self.config.port.unwrap_or(3000);\n        let host = self.config.host.as_deref().unwrap_or(\"0.0.0.0\");\n        let addr: SocketAddr = format!(\"{host}:{port}\").parse().expect(\"Invalid address\");\n\n        let listener = create_reusable_listener(addr).await.expect(\"Failed to create listener\");\n\n        if let Some(ready_cb) = ready {\n            ready_cb.call(Ok(()), ThreadsafeFunctionCallMode::NonBlocking);\n        }\n\n        loop {\n            tokio::select! {\n                Ok((tcp, remote_addr)) = listener.accept() => {\n                    let io = TokioIo::new(tcp);\n                    let config = self.config.clone();\n\n                    tokio::spawn(async move {\n                        if let Err(err) = http1::Builder::new()\n                            .serve_connection(io, hyper::service::service_fn(move |req| {\n                                handle_request(req, config.clone(), Some(remote_addr))\n                            }))\n                            .await\n                        {\n                            eprintln!(\"Error serving connection: {err:?}\");\n                        }\n                    });\n                },\n                _ = shutdown_rx.changed() => break,\n            }\n        }\n    }\n\n    #[cfg(unix)]\n    async fn start_unix_socket(\n        &self,\n        socket_path: &str,\n        ready: Option<ThreadsafeFunction<()>>,\n        shutdown_rx: &mut watch::Receiver<()>,\n    ) {\n        let path = Path::new(socket_path);\n\n        if path.exists() {\n            fs::remove_file(path).unwrap_or_else(|e| {\n                eprintln!(\"Warning: Could not remove existing socket file: {e}\");\n            });\n        }\n\n        let listener = UnixListener::bind(path).expect(\"Failed to bind Unix socket\");\n\n        if let Some(ready_cb) = ready {\n            ready_cb.call(Ok(()), ThreadsafeFunctionCallMode::NonBlocking);\n        }\n\n        loop {\n            tokio::select! {\n                Ok((stream, _)) = listener.accept() => {\n                    let io = TokioIo::new(stream);\n                    let config = self.config.clone();\n\n                    tokio::spawn(async move {\n                        if let Err(err) = http1::Builder::new()\n                            .serve_connection(io, hyper::service::service_fn(move |req| {\n                                handle_request(req, config.clone(), None)\n                            }))\n                            .await\n                        {\n                            eprintln!(\"Error serving connection: {err:?}\");\n                        }\n                    });\n                },\n                _ = shutdown_rx.changed() => break,\n            }\n        }\n\n        let _ = fs::remove_file(path);\n    }\n\n    #[napi]\n    pub fn close(&self) {\n        if let Some(tx) = &self.shutdown_tx {\n            let _ = tx.send(());\n        }\n    }\n}\n\nasync fn create_reusable_listener(addr: SocketAddr) -> std::io::Result<TcpListener> {\n    use socket2::{Domain, Protocol, Socket, Type};\n    use std::net::TcpListener as StdListener;\n\n    let domain = if addr.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 };\n    let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;\n\n    socket.set_reuse_address(true)?;\n\n    #[cfg(all(unix, not(target_os = \"solaris\"), not(target_os = \"illumos\")))]\n    socket.set_reuse_port(true)?;\n\n    socket.set_nonblocking(true)?;\n    socket.bind(&addr.into())?;\n    socket.listen(1024)?;\n\n    let std_listener: StdListener = socket.into();\n    TcpListener::from_std(std_listener)\n}\n"
  },
  {
    "path": "packages/core/src/server/handler.rs",
    "content": "use http_body_util::{BodyExt, Full, StreamBody};\nuse hyper::{\n    Request, Response,\n    body::{Bytes, Frame, Incoming},\n    header::{HeaderName, HeaderValue},\n};\n\nuse napi::{bindgen_prelude::External, threadsafe_function::ThreadsafeFunctionCallMode};\nuse serde_json::json;\n\nuse futures_util::stream;\nuse std::{convert::Infallible, net::SocketAddr, sync::Arc};\nuse tokio::sync::mpsc;\n\nuse crate::{\n    http::{\n        request::RequestCore,\n        response::{BoxedBody, ResponseChannel, ResponseMessage},\n    },\n    server::{\n        context::ContextObject,\n        core::ServerOptionsCore,\n        routes::{ROUTER, ResponseStrategy},\n    },\n    validation::parser::*,\n};\n\npub async fn handle_request(\n    req: Request<Incoming>,\n    config: ServerOptionsCore,\n    remote_addr: Option<SocketAddr>,\n) -> Result<Response<BoxedBody>, std::convert::Infallible> {\n    let method = req.method().to_string();\n    let pathname = req.uri().path().to_string();\n\n    let matched = match ROUTER.find(&method, &pathname) {\n        Some(m) => m,\n        None => {\n            return Ok(Response::builder()\n                .status(404)\n                .body(\n                    Full::new(Bytes::from_static(b\"Not Found\"))\n                        .map_err(|never| match never {})\n                        .boxed(),\n                )\n                .unwrap());\n        }\n    };\n\n    let route = matched.route;\n\n    if let ResponseStrategy::FullStatic(ref response) = route.strategy {\n        let (parts, body) = response.clone().into_parts();\n        let body_bytes = body.collect().await.unwrap().to_bytes();\n        return Ok(Response::from_parts(\n            parts,\n            Full::new(body_bytes).map_err(|never| match never {}).boxed(),\n        ));\n    }\n\n    if let ResponseStrategy::ParamTemplate { ref template, ref params, ref headers } =\n        route.strategy\n    {\n        let mut rendered = template.clone();\n\n        for param_name in params {\n            if let Some(value) = matched.params.get(param_name) {\n                let placeholder = format!(\"{{{{params.{param_name}}}}}\");\n                rendered = rendered.replace(&placeholder, value);\n            }\n        }\n\n        let mut response = Response::builder().status(200);\n        for (name, value) in headers {\n            response = response.header(name.as_str(), value.as_str());\n        }\n\n        return Ok(response\n            .body(Full::new(Bytes::from(rendered)).map_err(|never| match never {}).boxed())\n            .unwrap());\n    }\n\n    let mut req_core =\n        match RequestCore::new(req, remote_addr, config.trust_proxy.unwrap_or(false)).await {\n            Ok(core) => core,\n            Err(e) => {\n                eprintln!(\"Error creating request: {e}\");\n                return Ok(Response::builder()\n                    .status(400)\n                    .body(\n                        Full::new(Bytes::from_static(b\"Bad Request\"))\n                            .map_err(|never| match never {})\n                            .boxed(),\n                    )\n                    .unwrap());\n            }\n        };\n\n    req_core.params = matched.params.into_iter().collect();\n\n    if let Some(schema) = &route.schema {\n        if let Some(params_schema) = &schema.params\n            && let Err(e) = parse_params(&req_core.params, params_schema)\n        {\n            let error_msg = format!(\"Validation error in {}: {}\", e.field, e.message);\n            return Ok(Response::builder()\n                .status(400)\n                .header(\"Content-Type\", \"application/json\")\n                .body(\n                    Full::new(Bytes::from(\n                        json!({\n                            \"error\": \"Validation Error\",\n                            \"message\": error_msg\n                        })\n                        .to_string(),\n                    ))\n                    .map_err(|never| match never {})\n                    .boxed(),\n                )\n                .unwrap());\n        }\n\n        if let Some(query_schema) = &schema.query\n            && let Err(e) = parse_query(&req_core.query_raw, query_schema)\n        {\n            let error_msg = format!(\"Validation error in {}: {}\", e.field, e.message);\n            return Ok(Response::builder()\n                .status(400)\n                .header(\"Content-Type\", \"application/json\")\n                .body(\n                    Full::new(Bytes::from(\n                        json!({\n                            \"error\": \"Validation Error\",\n                            \"message\": error_msg\n                        })\n                        .to_string(),\n                    ))\n                    .map_err(|never| match never {})\n                    .boxed(),\n                )\n                .unwrap());\n        }\n\n        if let Some(body_schema) = &schema.body {\n            let has_body_method = matches!(method.as_str(), \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\");\n\n            if has_body_method {\n                if req_core.body.is_empty() {\n                    let error_msg = \"Request body is required\".to_string();\n                    return Ok(Response::builder()\n                        .status(400)\n                        .header(\"Content-Type\", \"application/json\")\n                        .body(\n                            Full::new(Bytes::from(\n                                json!({\n                                    \"error\": \"Validation Error\",\n                                    \"message\": error_msg\n                                })\n                                .to_string(),\n                            ))\n                            .map_err(|never| match never {})\n                            .boxed(),\n                        )\n                        .unwrap());\n                }\n\n                if let Err(e) = parse_body(req_core.body.as_ref(), body_schema) {\n                    let error_msg = format!(\"Validation error in {}: {}\", e.field, e.message);\n                    return Ok(Response::builder()\n                        .status(400)\n                        .header(\"Content-Type\", \"application/json\")\n                        .body(\n                            Full::new(Bytes::from(\n                                json!({\n                                    \"error\": \"Validation Error\",\n                                    \"message\": error_msg\n                                })\n                                .to_string(),\n                            ))\n                            .map_err(|never| match never {})\n                            .boxed(),\n                        )\n                        .unwrap());\n                }\n            }\n        }\n\n        if let Some(headers_schema) = &schema.headers\n            && let Err(e) = parse_headers(&req_core.headers_raw, headers_schema)\n        {\n            let error_msg = format!(\"Validation error in {}: {}\", e.field, e.message);\n            return Ok(Response::builder()\n                .status(400)\n                .header(\"Content-Type\", \"application/json\")\n                .body(\n                    Full::new(Bytes::from(\n                        json!({\n                            \"error\": \"Validation Error\",\n                            \"message\": error_msg\n                        })\n                        .to_string(),\n                    ))\n                    .map_err(|never| match never {})\n                    .boxed(),\n                )\n                .unwrap());\n        }\n    }\n\n    let (response_tx, mut response_rx) = mpsc::unbounded_channel();\n    let res_builder = Arc::new(ResponseChannel::new(response_tx));\n\n    let ctx_obj = ContextObject {\n        req: External::new(Arc::new(req_core)),\n        res: External::new(res_builder.clone()),\n    };\n\n    if let ResponseStrategy::Dynamic(handler) = route.strategy.clone() {\n        let _ = handler.call(ctx_obj, ThreadsafeFunctionCallMode::NonBlocking);\n    }\n\n    if let Some(first_msg) = response_rx.recv().await {\n        match first_msg {\n            ResponseMessage::Complete { status, headers, body } => {\n                let mut response = Response::builder().status(status);\n\n                for (name, value) in headers {\n                    if let (Ok(header_name), Ok(header_value)) =\n                        (name.parse::<HeaderName>(), value.parse::<HeaderValue>())\n                    {\n                        response = response.header(header_name, header_value);\n                    }\n                }\n\n                return Ok(response\n                    .body(Full::new(body).map_err(|never| match never {}).boxed())\n                    .unwrap());\n            }\n            ResponseMessage::StreamStart { status, headers } => {\n                let mut response = Response::builder().status(status);\n\n                for (name, value) in headers {\n                    if let (Ok(header_name), Ok(header_value)) =\n                        (name.parse::<HeaderName>(), value.parse::<HeaderValue>())\n                    {\n                        response = response.header(header_name, header_value);\n                    }\n                }\n\n                let stream = stream::unfold(response_rx, |mut rx| async move {\n                    match rx.recv().await {\n                        Some(ResponseMessage::StreamChunk { data }) => {\n                            Some((Ok(Frame::data(data)), rx))\n                        }\n                        Some(ResponseMessage::StreamEnd) | None => None,\n                        _ => None,\n                    }\n                });\n\n                let body = StreamBody::new(stream);\n                return Ok(response\n                    .body(body.map_err(|never: Infallible| match never {}).boxed())\n                    .unwrap());\n            }\n            _ => {}\n        }\n    }\n\n    Ok(Response::builder()\n        .status(200)\n        .body(Full::new(Bytes::new()).map_err(|never| match never {}).boxed())\n        .unwrap())\n}\n"
  },
  {
    "path": "packages/core/src/server/router.rs",
    "content": "use ahash::AHashMap;\nuse matchit::{Match, Router as MatchitRouter};\nuse parking_lot::RwLock;\nuse std::sync::Arc;\n\nuse super::routes::CompiledRoute;\n\npub struct TrieRouter {\n    inner: MatchitRouter<Arc<CompiledRoute>>,\n}\n\nimpl Default for TrieRouter {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl TrieRouter {\n    pub fn new() -> Self {\n        Self { inner: MatchitRouter::new() }\n    }\n\n    pub fn insert(&mut self, path: &str, route: Arc<CompiledRoute>) -> Result<(), String> {\n        self.inner.insert(path, route).map_err(|e| format!(\"Failed to insert route: {e}\"))\n    }\n\n    pub fn find<'a>(&'a self, path: &'a str) -> Option<Match<'a, 'a, &'a Arc<CompiledRoute>>> {\n        self.inner.at(path).ok()\n    }\n}\n\npub struct HttpRouter {\n    static_routes: AHashMap<Box<str>, Arc<CompiledRoute>>,\n    dynamic_routes: TrieRouter,\n}\n\nimpl Default for HttpRouter {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl HttpRouter {\n    pub fn new() -> Self {\n        Self { static_routes: AHashMap::new(), dynamic_routes: TrieRouter::new() }\n    }\n\n    pub fn insert(&mut self, route: CompiledRoute) -> Result<(), String> {\n        let route_arc = Arc::new(route);\n\n        if Self::is_static_route(&route_arc.path) {\n            self.static_routes.insert(route_arc.path.clone(), route_arc.clone());\n        } else {\n            self.dynamic_routes.insert(&route_arc.path, route_arc.clone())?;\n        }\n\n        Ok(())\n    }\n\n    pub fn find<'a>(&'a self, path: &'a str) -> Option<RouteMatch> {\n        if let Some(route) = self.static_routes.get(path) {\n            return Some(RouteMatch { route: route.clone(), params: AHashMap::new() });\n        }\n\n        if let Some(matched) = self.dynamic_routes.find(path) {\n            let mut params = AHashMap::new();\n\n            for (key, value) in matched.params.iter() {\n                params.insert(key.to_string(), value.to_string());\n            }\n\n            return Some(RouteMatch { route: matched.value.clone(), params });\n        }\n\n        None\n    }\n\n    fn is_static_route(path: &str) -> bool {\n        !path.contains(':') && !path.contains('*') && !path.contains('{')\n    }\n}\n\npub struct RouteMatch {\n    pub route: Arc<CompiledRoute>,\n    pub params: AHashMap<String, String>,\n}\n\npub struct GlobalRouter {\n    routers: RwLock<AHashMap<Box<str>, HttpRouter>>,\n}\n\nimpl Default for GlobalRouter {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl GlobalRouter {\n    pub fn new() -> Self {\n        Self { routers: RwLock::new(AHashMap::new()) }\n    }\n\n    pub fn insert(&self, method: &str, route: CompiledRoute) -> Result<(), String> {\n        let mut routers = self.routers.write();\n        let router = routers.entry(method.to_string().into_boxed_str()).or_default();\n\n        router.insert(route)\n    }\n\n    pub fn find(&self, method: &str, path: &str) -> Option<RouteMatch> {\n        let routers = self.routers.read();\n\n        if let Some(router) = routers.get(method) {\n            return router.find(path);\n        }\n\n        None\n    }\n\n    pub fn route_count(&self) -> usize {\n        let routers = self.routers.read();\n        routers.values().map(|r| r.static_routes.len()).sum()\n    }\n}\n"
  },
  {
    "path": "packages/core/src/server/routes.rs",
    "content": "use ahash::HashMap;\nuse std::sync::Arc;\n\nuse http_body_util::Full;\nuse hyper::Response;\nuse hyper::body::Bytes;\n\nuse napi::Error;\nuse napi::{bindgen_prelude::Function, threadsafe_function::ThreadsafeFunction};\n\nuse base64::Engine;\nuse base64::engine::general_purpose;\n\nuse once_cell::sync::Lazy;\nuse serde_json::{Value, from_str, from_value};\n\nuse crate::server::context::ContextObject;\nuse crate::server::router::GlobalRouter;\nuse crate::validation::types::SchemaType;\n\npub type RouteHandler = ThreadsafeFunction<ContextObject, (), ContextObject, napi::Status, false>;\n\npub struct CompiledRoute {\n    pub method: Box<str>,\n    pub path: Box<str>,\n    pub segments: Box<[Box<str>]>,\n    pub strategy: ResponseStrategy,\n    pub schema: Option<RouteSchema>,\n}\n\n#[derive(Clone)]\npub struct RouteSchema {\n    pub params: Option<SchemaType>,\n    pub query: Option<SchemaType>,\n    pub body: Option<SchemaType>,\n    pub headers: Option<SchemaType>,\n}\n\npub static ROUTER: Lazy<GlobalRouter> = Lazy::new(GlobalRouter::new);\n\n#[napi(object)]\npub struct Route {\n    pub path: String,\n    #[napi(ts_type = \"'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'TRACE'\")]\n    pub method: String,\n    #[napi(ts_type = \"RouteHandler\")]\n    pub handler: Function<'static, ContextObject, ()>,\n    pub schema: Option<String>,\n    pub static_response: Option<String>,\n}\n\n#[derive(Clone)]\npub enum ResponseStrategy {\n    Dynamic(Arc<RouteHandler>),\n    FullStatic(Response<Full<Bytes>>),\n    ParamTemplate { template: String, params: Vec<String>, headers: HashMap<String, String> },\n}\n\nfn convert_path_to_matchit_format(path: &str) -> String {\n    if !path.contains(':') {\n        return path.to_string();\n    }\n\n    let parts: Vec<&str> = path.split('/').collect();\n    let converted_parts: Vec<String> = parts\n        .iter()\n        .map(|part| {\n            if let Some(stripped) = part.strip_prefix(':') {\n                format!(\"{{{stripped}}}\")\n            } else {\n                part.to_string()\n            }\n        })\n        .collect();\n\n    converted_parts.join(\"/\")\n}\n\npub fn insert_route(route: Route) -> napi::Result<()> {\n    let method_key: Box<str> = route.method.clone().into_boxed_str();\n    let converted_path = convert_path_to_matchit_format(&route.path);\n\n    let segments: Vec<Box<str>> = converted_path\n        .split('/')\n        .filter(|s| !s.is_empty())\n        .map(|s| s.to_string().into_boxed_str())\n        .collect();\n\n    let strategy = if let Some(static_json) = route.static_response {\n        let static_info: Value = from_str(&static_json)\n            .map_err(|e| Error::from_reason(format!(\"Invalid static response: {e}\")))?;\n\n        match static_info[\"type\"].as_str() {\n            Some(\"full_static\") => {\n                let status = static_info[\"status\"].as_u64().unwrap_or(200) as u16;\n\n                let body_base64 = static_info[\"body\"]\n                    .as_str()\n                    .ok_or_else(|| Error::from_reason(\"Missing body field in static response\"))?;\n\n                let body_bytes = general_purpose::STANDARD\n                    .decode(body_base64)\n                    .map_err(|e| Error::from_reason(format!(\"Invalid base64 body: {e}\")))?;\n\n                let mut response = Response::builder().status(status);\n\n                if let Some(headers) = static_info[\"headers\"].as_object() {\n                    for (name, value) in headers {\n                        if let Some(v) = value.as_str() {\n                            response = response.header(name.as_str(), v);\n                        }\n                    }\n                }\n\n                let response = response\n                    .body(Full::new(Bytes::from(body_bytes)))\n                    .map_err(|e| Error::from_reason(format!(\"Failed to build response: {e}\")))?;\n\n                ResponseStrategy::FullStatic(response)\n            }\n            Some(\"param_template\") => {\n                let template = static_info[\"template\"]\n                    .as_str()\n                    .ok_or_else(|| Error::from_reason(\"Missing template field\"))?\n                    .to_string();\n\n                let params: Vec<String> = static_info[\"params\"]\n                    .as_array()\n                    .ok_or_else(|| Error::from_reason(\"Missing params field\"))?\n                    .iter()\n                    .filter_map(|v| v.as_str().map(|s| s.to_string()))\n                    .collect();\n\n                let headers: HashMap<String, String> = static_info[\"headers\"]\n                    .as_object()\n                    .ok_or_else(|| Error::from_reason(\"Missing headers field\"))?\n                    .iter()\n                    .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))\n                    .collect();\n\n                ResponseStrategy::ParamTemplate { template, params, headers }\n            }\n            _ => {\n                let tsfn = route.handler.build_threadsafe_function().build()?;\n                ResponseStrategy::Dynamic(Arc::new(tsfn))\n            }\n        }\n    } else {\n        let tsfn = route.handler.build_threadsafe_function().build()?;\n        ResponseStrategy::Dynamic(Arc::new(tsfn))\n    };\n\n    let schema = if let Some(schema_json) = route.schema {\n        let parsed: Value = from_str(&schema_json)\n            .map_err(|e| Error::from_reason(format!(\"Invalid schema JSON: {e}\")))?;\n\n        Some(RouteSchema {\n            params: parsed.get(\"params\").and_then(|v| from_value(v.clone()).ok()),\n            query: parsed.get(\"query\").and_then(|v| from_value(v.clone()).ok()),\n            body: parsed.get(\"body\").and_then(|v| from_value(v.clone()).ok()),\n            headers: parsed.get(\"headers\").and_then(|v| from_value(v.clone()).ok()),\n        })\n    } else {\n        None\n    };\n\n    let compiled = CompiledRoute {\n        method: method_key.clone(),\n        path: converted_path.into_boxed_str(),\n        segments: segments.into_boxed_slice(),\n        strategy,\n        schema,\n    };\n\n    ROUTER.insert(&route.method, compiled).map_err(Error::from_reason)?;\n    Ok(())\n}\n"
  },
  {
    "path": "packages/core/src/server.rs",
    "content": "pub mod context;\npub mod core;\npub mod handler;\npub mod router;\npub mod routes;\n\npub use core::ServerCore;\npub use router::{GlobalRouter, HttpRouter};\npub use routes::{CompiledRoute, ROUTER, Route};\n"
  },
  {
    "path": "packages/core/src/validation/parser.rs",
    "content": "use serde_json::{Map, Value, from_slice};\n\nuse super::types::*;\nuse crate::validation::validate_value;\n\nuse std::collections::HashMap;\n\npub fn parse_params(\n    params: &HashMap<String, String>,\n    schema: &SchemaType,\n) -> Result<Value, ValidationError> {\n    let mut obj = Map::new();\n    for (key, value) in params {\n        obj.insert(key.clone(), Value::String(value.clone()));\n    }\n\n    validate_value(&Value::Object(obj), schema, \"params\")\n}\n\npub fn parse_query(\n    query: &HashMap<String, Vec<String>>,\n    schema: &SchemaType,\n) -> Result<Value, ValidationError> {\n    let mut obj = Map::new();\n    for (key, values) in query {\n        if values.len() == 1 {\n            obj.insert(key.clone(), Value::String(values[0].clone()));\n        } else if values.is_empty() {\n            obj.insert(key.clone(), Value::Null);\n        } else {\n            let arr: Vec<Value> = values.iter().map(|v| Value::String(v.clone())).collect();\n            obj.insert(key.clone(), Value::Array(arr));\n        }\n    }\n\n    validate_value(&Value::Object(obj), schema, \"query\")\n}\n\npub fn parse_body(body: &[u8], schema: &SchemaType) -> Result<Value, ValidationError> {\n    if body.is_empty() {\n        if let SchemaType::Object { optional: true, default, .. } = schema {\n            return Ok(default.clone().unwrap_or(Value::Null));\n        }\n        return Err(ValidationError::new(\"body\", \"Request body is required\"));\n    }\n\n    let body_value: Value =\n        from_slice(body).map_err(|_| ValidationError::new(\"body\", \"Invalid JSON\"))?;\n\n    validate_value(&body_value, schema, \"body\")\n}\n\npub fn parse_headers(\n    headers: &HashMap<String, String>,\n    schema: &SchemaType,\n) -> Result<Value, ValidationError> {\n    let mut obj = Map::new();\n    for (key, value) in headers {\n        obj.insert(key.clone(), Value::String(value.clone()));\n    }\n\n    validate_value(&Value::Object(obj), schema, \"headers\")\n}\n"
  },
  {
    "path": "packages/core/src/validation/parser_tests.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use super::super::parser::*;\n    use super::super::types::*;\n    use serde_json::json;\n    use std::collections::HashMap;\n\n    #[test]\n    fn test_parse_params_basic() {\n        let mut params = HashMap::new();\n        params.insert(\"id\".to_string(), \"123\".to_string());\n        params.insert(\"name\".to_string(), \"john\".to_string());\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"id\".to_string(),\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n        );\n        shape.insert(\n            \"name\".to_string(),\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_params(&params, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_query_single_value() {\n        let mut query = HashMap::new();\n        query.insert(\"page\".to_string(), vec![\"1\".to_string()]);\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"page\".to_string(),\n            SchemaType::Number { optional: false, default: None, constraints: vec![] },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_query(&query, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_query_multiple_values() {\n        let mut query = HashMap::new();\n        query.insert(\"tags\".to_string(), vec![\"rust\".to_string(), \"web\".to_string()]);\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"tags\".to_string(),\n            SchemaType::Array {\n                optional: false,\n                default: None,\n                constraints: vec![],\n                item: Box::new(SchemaType::String {\n                    optional: false,\n                    default: None,\n                    constraints: vec![],\n                }),\n            },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_query(&query, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_body_valid_json() {\n        let body = br#\"{\"name\":\"Alice\",\"age\":25}\"#;\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"name\".to_string(),\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n        );\n        shape.insert(\n            \"age\".to_string(),\n            SchemaType::Number { optional: false, default: None, constraints: vec![] },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_body(body, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_body_invalid_json() {\n        let body = b\"not valid json\";\n\n        let schema = SchemaType::Object { optional: false, default: None, shape: HashMap::new() };\n\n        let result = parse_body(body, &schema);\n        assert!(result.is_err());\n    }\n\n    #[test]\n    fn test_parse_body_empty_with_optional() {\n        let body = b\"\";\n\n        let schema =\n            SchemaType::Object { optional: true, default: Some(json!({})), shape: HashMap::new() };\n\n        let result = parse_body(body, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_body_empty_required() {\n        let body = b\"\";\n\n        let schema = SchemaType::Object { optional: false, default: None, shape: HashMap::new() };\n\n        let result = parse_body(body, &schema);\n        assert!(result.is_err());\n    }\n\n    #[test]\n    fn test_parse_headers() {\n        let mut headers = HashMap::new();\n        headers.insert(\"authorization\".to_string(), \"Bearer token123\".to_string());\n        headers.insert(\"content-type\".to_string(), \"application/json\".to_string());\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"authorization\".to_string(),\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_headers(&headers, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_params_with_validation() {\n        let mut params = HashMap::new();\n        params.insert(\"id\".to_string(), \"550e8400-e29b-41d4-a716-446655440000\".to_string());\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"id\".to_string(),\n            SchemaType::String {\n                optional: false,\n                default: None,\n                constraints: vec![StringConstraint::Uuid],\n            },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_params(&params, &schema);\n        assert!(result.is_ok());\n    }\n\n    #[test]\n    fn test_parse_params_validation_fails() {\n        let mut params = HashMap::new();\n        params.insert(\"id\".to_string(), \"not-a-uuid\".to_string());\n\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"id\".to_string(),\n            SchemaType::String {\n                optional: false,\n                default: None,\n                constraints: vec![StringConstraint::Uuid],\n            },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let result = parse_params(&params, &schema);\n        assert!(result.is_err());\n    }\n}\n"
  },
  {
    "path": "packages/core/src/validation/tests.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use super::super::{types::*, validators::*};\n    use serde_json::{Value, json};\n    use std::collections::HashMap;\n\n    #[test]\n    fn test_string_min_length() {\n        let constraints = vec![StringConstraint::Min { value: 5 }];\n\n        assert!(validate_string(\"hello\", &constraints).is_ok());\n        assert!(validate_string(\"hi\", &constraints).is_err());\n    }\n\n    #[test]\n    fn test_string_max_length() {\n        let constraints = vec![StringConstraint::Max { value: 5 }];\n\n        assert!(validate_string(\"hello\", &constraints).is_ok());\n        assert!(validate_string(\"hello world\", &constraints).is_err());\n    }\n\n    #[test]\n    fn test_string_email() {\n        let constraints = vec![StringConstraint::Email];\n\n        assert!(validate_string(\"user@example.com\", &constraints).is_ok());\n        assert!(validate_string(\"invalid-email\", &constraints).is_err());\n        assert!(validate_string(\"no@domain\", &constraints).is_err());\n    }\n\n    #[test]\n    fn test_string_uuid() {\n        let constraints = vec![StringConstraint::Uuid];\n\n        assert!(validate_string(\"550e8400-e29b-41d4-a716-446655440000\", &constraints).is_ok());\n        assert!(validate_string(\"not-a-uuid\", &constraints).is_err());\n    }\n\n    #[test]\n    fn test_number_min() {\n        let constraints = vec![NumberConstraint::Min { value: 10.0 }];\n\n        assert!(validate_number(15.0, &constraints).is_ok());\n        assert!(validate_number(5.0, &constraints).is_err());\n    }\n\n    #[test]\n    fn test_number_max() {\n        let constraints = vec![NumberConstraint::Max { value: 100.0 }];\n\n        assert!(validate_number(50.0, &constraints).is_ok());\n        assert!(validate_number(150.0, &constraints).is_err());\n    }\n\n    #[test]\n    fn test_number_int() {\n        let constraints = vec![NumberConstraint::Int];\n\n        assert!(validate_number(42.0, &constraints).is_ok());\n        assert!(validate_number(42.5, &constraints).is_err());\n    }\n\n    #[test]\n    fn test_number_positive() {\n        let constraints = vec![NumberConstraint::Positive];\n\n        assert!(validate_number(10.0, &constraints).is_ok());\n        assert!(validate_number(-5.0, &constraints).is_err());\n        assert!(validate_number(0.0, &constraints).is_err());\n    }\n\n    #[test]\n    fn test_validate_string_value() {\n        let schema = SchemaType::String {\n            optional: false,\n            default: None,\n            constraints: vec![StringConstraint::Min { value: 3 }],\n        };\n\n        assert!(validate_value(&json!(\"hello\"), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!(\"hi\"), &schema, \"field\").is_err());\n        assert!(validate_value(&Value::Null, &schema, \"field\").is_err());\n    }\n\n    #[test]\n    fn test_validate_optional_with_default() {\n        let schema = SchemaType::String {\n            optional: true,\n            default: Some(\"default\".to_string()),\n            constraints: vec![],\n        };\n\n        let result = validate_value(&Value::Null, &schema, \"field\").unwrap();\n        assert_eq!(result, json!(\"default\"));\n    }\n\n    #[test]\n    fn test_validate_number_from_string() {\n        let schema = SchemaType::Number { optional: false, default: None, constraints: vec![] };\n\n        assert!(validate_value(&json!(\"42\"), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!(\"not-a-number\"), &schema, \"field\").is_err());\n    }\n\n    #[test]\n    fn test_validate_boolean_from_string() {\n        let schema = SchemaType::Boolean { optional: false, default: None };\n\n        assert_eq!(validate_value(&json!(\"true\"), &schema, \"field\").unwrap(), json!(true));\n        assert_eq!(validate_value(&json!(\"false\"), &schema, \"field\").unwrap(), json!(false));\n        assert_eq!(validate_value(&json!(\"1\"), &schema, \"field\").unwrap(), json!(true));\n        assert_eq!(validate_value(&json!(\"0\"), &schema, \"field\").unwrap(), json!(false));\n    }\n\n    #[test]\n    fn test_validate_array() {\n        let item_schema =\n            SchemaType::Number { optional: false, default: None, constraints: vec![] };\n\n        let schema = SchemaType::Array {\n            optional: false,\n            default: None,\n            constraints: vec![ArrayConstraint::Min { value: 2 }],\n            item: Box::new(item_schema),\n        };\n\n        assert!(validate_value(&json!([1, 2, 3]), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!([1]), &schema, \"field\").is_err());\n    }\n\n    #[test]\n    fn test_validate_object() {\n        let mut shape = HashMap::new();\n        shape.insert(\n            \"name\".to_string(),\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n        );\n        shape.insert(\n            \"age\".to_string(),\n            SchemaType::Number {\n                optional: false,\n                default: None,\n                constraints: vec![NumberConstraint::Positive],\n            },\n        );\n\n        let schema = SchemaType::Object { optional: false, default: None, shape };\n\n        let valid_value = json!({\n            \"name\": \"Alice\",\n            \"age\": 25\n        });\n\n        let invalid_value = json!({\n            \"name\": \"Bob\",\n            \"age\": -5\n        });\n\n        assert!(validate_value(&valid_value, &schema, \"field\").is_ok());\n        assert!(validate_value(&invalid_value, &schema, \"field\").is_err());\n    }\n\n    #[test]\n    fn test_validate_literal() {\n        let schema = SchemaType::Literal { optional: false, default: None, value: json!(\"admin\") };\n\n        assert!(validate_value(&json!(\"admin\"), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!(\"user\"), &schema, \"field\").is_err());\n    }\n\n    #[test]\n    fn test_validate_union() {\n        let schemas = vec![\n            SchemaType::String { optional: false, default: None, constraints: vec![] },\n            SchemaType::Number { optional: false, default: None, constraints: vec![] },\n        ];\n\n        let schema = SchemaType::Union { optional: false, default: None, schemas };\n\n        assert!(validate_value(&json!(\"hello\"), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!(42), &schema, \"field\").is_ok());\n        assert!(validate_value(&json!(true), &schema, \"field\").is_err());\n    }\n}\n"
  },
  {
    "path": "packages/core/src/validation/types.rs",
    "content": "use serde::{Deserialize, Serialize};\nuse serde_json::Value;\n\nuse std::collections::HashMap;\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\npub enum SchemaType {\n    String {\n        optional: bool,\n        default: Option<String>,\n        constraints: Vec<StringConstraint>,\n    },\n    Number {\n        optional: bool,\n        default: Option<f64>,\n        constraints: Vec<NumberConstraint>,\n    },\n    Boolean {\n        optional: bool,\n        default: Option<bool>,\n    },\n    Array {\n        optional: bool,\n        default: Option<Value>,\n        constraints: Vec<ArrayConstraint>,\n        item: Box<SchemaType>,\n    },\n    Object {\n        optional: bool,\n        default: Option<Value>,\n        shape: HashMap<String, SchemaType>,\n    },\n    Literal {\n        optional: bool,\n        default: Option<Value>,\n        value: Value,\n    },\n    Union {\n        optional: bool,\n        default: Option<Value>,\n        schemas: Vec<SchemaType>,\n    },\n}\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\npub enum StringConstraint {\n    Min { value: usize },\n    Max { value: usize },\n    Length { value: usize },\n    Email,\n    Url,\n    Uuid,\n    Regex { value: String },\n}\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\npub enum NumberConstraint {\n    Min { value: f64 },\n    Max { value: f64 },\n    Int,\n    Positive,\n    Negative,\n}\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\npub enum ArrayConstraint {\n    Min { value: usize },\n    Max { value: usize },\n    Length { value: usize },\n}\n\n#[derive(Debug, Clone)]\npub struct ValidationError {\n    pub field: String,\n    pub message: String,\n}\n\nimpl ValidationError {\n    pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {\n        Self { field: field.into(), message: message.into() }\n    }\n}\n"
  },
  {
    "path": "packages/core/src/validation/validators.rs",
    "content": "use super::types::*;\n\nuse regex::Regex;\nuse serde_json::{Map, Number, Value};\n\npub fn validate_string(\n    value: &str,\n    constraints: &[StringConstraint],\n) -> Result<(), ValidationError> {\n    let uuid_regex = Regex::new(\n        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}$\",\n    )\n    .unwrap();\n    let email_regex = Regex::new(r\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\").unwrap();\n\n    for constraint in constraints {\n        match constraint {\n            StringConstraint::Min { value: min } => {\n                if value.len() < *min {\n                    return Err(ValidationError::new(\n                        \"\",\n                        format!(\"String must be at least {min} characters long\"),\n                    ));\n                }\n            }\n            StringConstraint::Max { value: max } => {\n                if value.len() > *max {\n                    return Err(ValidationError::new(\n                        \"\",\n                        format!(\"String must be at most {max} characters long\"),\n                    ));\n                }\n            }\n            StringConstraint::Length { value: length } => {\n                if value.len() != *length {\n                    return Err(ValidationError::new(\n                        \"\",\n                        format!(\"String must be exactly {length} characters long\"),\n                    ));\n                }\n            }\n            StringConstraint::Email => {\n                if !email_regex.is_match(value) {\n                    return Err(ValidationError::new(\"\", \"Invalid email format\"));\n                }\n            }\n            StringConstraint::Url => {\n                if !value.starts_with(\"http://\") && !value.starts_with(\"https://\") {\n                    return Err(ValidationError::new(\"\", \"Invalid URL format\"));\n                }\n            }\n            StringConstraint::Uuid => {\n                if !uuid_regex.is_match(value) {\n                    return Err(ValidationError::new(\"\", \"Invalid UUID format\"));\n                }\n            }\n            StringConstraint::Regex { value: pattern } => {\n                let regex = Regex::new(pattern)\n                    .map_err(|_| ValidationError::new(\"\", \"Invalid regex pattern\"))?;\n\n                if !regex.is_match(value) {\n                    return Err(ValidationError::new(\"\", \"String does not match pattern\"));\n                }\n            }\n        }\n    }\n    Ok(())\n}\n\npub fn validate_number(\n    value: f64,\n    constraints: &[NumberConstraint],\n) -> Result<(), ValidationError> {\n    for constraint in constraints {\n        match constraint {\n            NumberConstraint::Min { value: min } => {\n                if value < *min {\n                    return Err(ValidationError::new(\"\", format!(\"Number must be at least {min}\")));\n                }\n            }\n            NumberConstraint::Max { value: max } => {\n                if value > *max {\n                    return Err(ValidationError::new(\"\", format!(\"Number must be at most {max}\")));\n                }\n            }\n            NumberConstraint::Int => {\n                if value.fract() != 0.0 {\n                    return Err(ValidationError::new(\"\", \"Number must be an integer\"));\n                }\n            }\n            NumberConstraint::Positive => {\n                if value <= 0.0 {\n                    return Err(ValidationError::new(\"\", \"Number must be positive\"));\n                }\n            }\n            NumberConstraint::Negative => {\n                if value >= 0.0 {\n                    return Err(ValidationError::new(\"\", \"Number must be negative\"));\n                }\n            }\n        }\n    }\n    Ok(())\n}\n\npub fn validate_value(\n    value: &Value,\n    schema: &SchemaType,\n    field_path: &str,\n) -> Result<Value, ValidationError> {\n    match schema {\n        SchemaType::String { optional, default, constraints } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default\n                        .as_ref()\n                        .map(|d| Value::String(d.clone()))\n                        .unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            let str_value = value\n                .as_str()\n                .ok_or_else(|| ValidationError::new(field_path, \"Expected string\"))?;\n\n            validate_string(str_value, constraints)\n                .map_err(|e| ValidationError::new(field_path, e.message))?;\n\n            Ok(value.clone())\n        }\n        SchemaType::Number { optional, default, constraints } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default\n                        .as_ref()\n                        .map(|d| Value::Number(Number::from_f64(*d).unwrap()))\n                        .unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            let num_value = if let Some(n) = value.as_f64() {\n                n\n            } else if let Some(s) = value.as_str() {\n                s.parse::<f64>()\n                    .map_err(|_| ValidationError::new(field_path, \"Invalid number format\"))?\n            } else {\n                return Err(ValidationError::new(field_path, \"Expected number\"));\n            };\n\n            validate_number(num_value, constraints)\n                .map_err(|e| ValidationError::new(field_path, e.message))?;\n\n            Ok(Value::Number(Number::from_f64(num_value).unwrap()))\n        }\n        SchemaType::Boolean { optional, default } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default.as_ref().map(|d| Value::Bool(*d)).unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            if let Some(b) = value.as_bool() {\n                Ok(Value::Bool(b))\n            } else if let Some(s) = value.as_str() {\n                match s.to_lowercase().as_str() {\n                    \"true\" | \"1\" => Ok(Value::Bool(true)),\n                    \"false\" | \"0\" => Ok(Value::Bool(false)),\n                    _ => Err(ValidationError::new(field_path, \"Invalid boolean value\")),\n                }\n            } else {\n                Err(ValidationError::new(field_path, \"Expected boolean\"))\n            }\n        }\n        SchemaType::Array { optional, default, constraints, item } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default.clone().unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            let arr = value\n                .as_array()\n                .ok_or_else(|| ValidationError::new(field_path, \"Expected array\"))?;\n\n            for constraint in constraints {\n                match constraint {\n                    ArrayConstraint::Min { value: min } => {\n                        if arr.len() < *min {\n                            return Err(ValidationError::new(\n                                field_path,\n                                format!(\"Array must have at least {min} items\"),\n                            ));\n                        }\n                    }\n                    ArrayConstraint::Max { value: max } => {\n                        if arr.len() > *max {\n                            return Err(ValidationError::new(\n                                field_path,\n                                format!(\"Array must have at most {max} items\"),\n                            ));\n                        }\n                    }\n                    ArrayConstraint::Length { value: length } => {\n                        if arr.len() != *length {\n                            return Err(ValidationError::new(\n                                field_path,\n                                format!(\"Array must have exactly {length} items\"),\n                            ));\n                        }\n                    }\n                }\n            }\n\n            let mut validated_items = Vec::new();\n            for (i, item_value) in arr.iter().enumerate() {\n                let item_path = format!(\"{field_path}[{i}]\");\n                let validated = validate_value(item_value, item, &item_path)?;\n                validated_items.push(validated);\n            }\n\n            Ok(Value::Array(validated_items))\n        }\n        SchemaType::Object { optional, default, shape } => {\n            if value.is_null() || (value.is_object() && value.as_object().unwrap().is_empty()) {\n                if *optional {\n                    return Ok(default.clone().unwrap_or(Value::Null));\n                }\n\n                if shape.is_empty() {\n                    return Ok(Value::Object(Map::new()));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            let obj = value\n                .as_object()\n                .ok_or_else(|| ValidationError::new(field_path, \"Expected object\"))?;\n\n            let mut validated_obj = Map::new();\n\n            for (key, field_schema) in shape {\n                let field_value = obj.get(key).cloned().unwrap_or(Value::Null);\n                let new_path =\n                    if field_path.is_empty() { key.clone() } else { format!(\"{field_path}.{key}\") };\n                let validated = validate_value(&field_value, field_schema, &new_path)?;\n\n                if !validated.is_null()\n                    || matches!(\n                        field_schema,\n                        SchemaType::String { optional: false, .. }\n                            | SchemaType::Number { optional: false, .. }\n                            | SchemaType::Boolean { optional: false, .. }\n                    )\n                {\n                    validated_obj.insert(key.clone(), validated);\n                }\n            }\n\n            Ok(Value::Object(validated_obj))\n        }\n        SchemaType::Literal { optional, default, value: literal_value } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default.clone().unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            let compare_value = if value.is_string() {\n                value.clone()\n            } else if literal_value.is_string() && !value.is_string() {\n                Value::String(value.to_string())\n            } else {\n                value.clone()\n            };\n\n            if &compare_value != literal_value {\n                return Err(ValidationError::new(\n                    field_path,\n                    format!(\"Value must be exactly {literal_value:?}\"),\n                ));\n            }\n\n            Ok(value.clone())\n        }\n        SchemaType::Union { optional, default, schemas } => {\n            if value.is_null() {\n                if *optional {\n                    return Ok(default.clone().unwrap_or(Value::Null));\n                }\n                return Err(ValidationError::new(field_path, \"Field is required\"));\n            }\n\n            for schema in schemas {\n                if let Ok(validated) = validate_value(value, schema, field_path) {\n                    return Ok(validated);\n                }\n            }\n\n            Err(ValidationError::new(field_path, \"Value does not match any union type\"))\n        }\n    }\n}\n"
  },
  {
    "path": "packages/core/src/validation.rs",
    "content": "pub mod parser;\npub mod parser_tests;\npub mod tests;\npub mod types;\npub mod validators;\n\npub use parser::*;\npub use types::*;\npub use validators::*;\n"
  },
  {
    "path": "packages/core/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"],\n  \"references\": []\n}\n"
  },
  {
    "path": "packages/kitojs/.gitignore",
    "content": "dist/\ndocs/"
  },
  {
    "path": "packages/kitojs/package.json",
    "content": "{\n  \"name\": \"kitojs\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"🐺 The high-performance, type-safe and modern TypeScript web framework written in Rust.\",\n  \"scripts\": {\n    \"build\": \"tsdown\",\n\n    \"test\": \"vitest run\",\n    \"test:watch\": \"vitest\",\n    \"test:coverage\": \"vitest run --coverage\",\n\n    \"docs\": \"typedoc\",\n    \"docs:watch\": \"typedoc --watch\",\n    \"docs:serve\": \"pnpm dlx serve docs\"\n  },\n\n  \"dependencies\": {\n    \"@kitojs/kito-core\": \"workspace:*\",\n    \"acorn\": \"^8.15.0\",\n    \"acorn-walk\": \"^8.3.4\"\n  },\n  \"devDependencies\": {\n    \"@kitojs/types\": \"workspace:*\",\n    \"@vitest/coverage-v8\": \"^4.0.9\",\n    \"tsdown\": \"^0.15.0\",\n    \"typedoc\": \"^0.28.14\",\n    \"vitest\": \"^4.0.9\"\n  },\n  \"peerDependencies\": {\n    \"typescript\": \"^5.9.2\"\n  },\n\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/kitojs/kito.git\"\n  },\n  \"homepage\": \"https://kito.pages.dev\",\n  \"bugs\": {\n    \"url\": \"https://github.com/kitojs/kito/issues\"\n  },\n\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Nehuén\",\n    \"url\": \"https://github.com/nehu3n\"\n  },\n\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.js\",\n      \"types\": \"./dist/index.d.ts\"\n    }\n  },\n\n  \"files\": [\n    \"dist\",\n    \"readme.md\",\n    \"package.json\"\n  ]\n}\n"
  },
  {
    "path": "packages/kitojs/readme.md",
    "content": "<div align=\"center\">\n  <img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-banner.svg\" width=\"220px\" />\n  \n  <br />\n  <br />\n  \n  <p>\n    <strong>High-performance</strong>, fully <strong>type-safe</strong>, and modern web framework for <strong>TypeScript</strong>.  \n    Powered by <strong>Rust</strong> for extreme speed and low memory usage.\n  </p>\n</div>\n\n---\n\n- **Extreme performance** – Rust core optimized for extreme speed & efficiency. **See the [benchmarks](https://github.com/kitojs/kito/tree/main/bench).**\n- **Type-safe** – full TypeScript support with end-to-end safety and exceptional DX.\n- **Schema validation** – built-in validation with zero bloat.  \n- **Middleware system** – composable and flexible like you expect.\n- **Cross-platform** – runs on Node.js, Bun, and Deno.  \n\n---\n\n## 🚀 Quick Start\n\nYou can add **Kito** to an existing project:\n\n```bash\npnpm add kitojs\n\n# Or: npm/yarn/bun add kitojs\n# Or: deno add npm:kitojs\n```\n\nOr create a new project instantly with the [official starter](https://github.com/kitojs/create-kitojs):\n\n```bash\npnpm create kitojs\n\n# Or: npm/yarn/bun create kitojs\n# Or: deno init --npm kitojs\n```\n\n### Minimal Example\n\n```ts\nimport { server } from \"kitojs\";\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"hello world!\");\n});\n\napp.listen(3000);\n```\n\n<details>\n  <summary><strong>Fluent style</strong></summary>\n\n  Kito also supports fluent style. You can chain all methods. **See the examples [here](https://github.com/kitojs/kito/tree/main/examples/fluent).**\n\n  ```ts\n  import { server } from \"kitojs\";\n\n  server()\n    .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n    .listen(3000);\n  ```\n</details>\n\n---\n\n## 📚 Documentation\n\nFull docs available at the [**official website**](https://kito.pages.dev).\nYou can also explore ready-to-run [examples](https://github.com/kitojs/kito/tree/main/examples).\n\n---\n\n## 🤝 Contributing\n\nWe 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.\n\n---\n\n## 📄 License\n\nLicensed under the [MIT License](https://github.com/kitojs/kito/blob/main/license).\n\n---\n"
  },
  {
    "path": "packages/kitojs/src/helpers/middleware.ts",
    "content": "import type { MiddlewareDefinition, MiddlewareHandler } from \"@kitojs/types\";\n\n/**\n * Creates a typed middleware definition.\n *\n * @template TExtensions - Type of context extensions available in the middleware\n * @param handler - Middleware function that processes requests\n * @returns Middleware definition object\n *\n * @example\n * ```typescript\n * import { middleware } from 'kitojs';\n *\n * // Basic middleware\n * const logger = middleware((ctx, next) => {\n *   console.log(`${ctx.req.method} ${ctx.req.url}`);\n *   next();\n * });\n *\n * // Authentication middleware\n * const auth = middleware((ctx, next) => {\n *   const token = ctx.req.headers.authorization;\n *\n *   if (!token || !verifyToken(token)) {\n *     ctx.res.status(401).send('Unauthorized');\n *     return;\n *   }\n *\n *   next();\n * });\n *\n * // Async middleware\n * const asyncAuth = middleware(async (ctx, next) => {\n *   const user = await validateUser(ctx.req.headers.authorization);\n *   if (!user) {\n *     ctx.res.status(401).send('Unauthorized');\n *     return;\n *   }\n *   await next();\n * });\n *\n * // Using middleware\n * app.use(logger); // global\n *\n * // Route middleware\n * app.get('/protected', [auth], ctx => {\n *   ctx.res.send('Secret data');\n * });\n * ```\n */\nexport function middleware<TSchema = unknown, TExtensions = unknown>(\n  handler: MiddlewareHandler<TSchema, TExtensions>,\n): MiddlewareDefinition {\n  return {\n    type: \"function\",\n    handler: handler as MiddlewareHandler,\n    global: false,\n  };\n}\n"
  },
  {
    "path": "packages/kitojs/src/helpers/schema.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  SchemaDefinition,\n  JSONSchemaDefinition,\n  InferJSONSchemaRequest,\n} from \"@kitojs/types\";\n\nimport { convertJSONSchema } from \"../schemas/jsonSchema\";\n\n/**\n * Creates a typed schema definition for request validation.\n * This is a type helper that preserves schema structure for type inference.\n *\n * @template T - Schema definition type\n * @param definition - Schema definition object\n * @returns The same schema definition with preserved types\n *\n * @example\n * ```typescript\n * import { schema, t } from 'kitojs';\n *\n * const userSchema = schema({\n *   params: t.object({\n *     id: t.str().uuid()\n *   }),\n *   query: t.object({\n *     limit: t.num().min(1).max(100).default(10)\n *   }),\n *   body: t.object({\n *     name: t.str().min(1),\n *     email: t.str().email()\n *   }),\n *   headers: t.object({\n *     authorization: t.str()\n *   })\n * });\n *\n * app.post('/users/:id', ({ req, res }) => {\n *   // All request parts are type-safe and validated\n *   const id = req.params.id; // string (UUID validated)\n *   const limit = req.query.limit; // number\n *   const name = req.body.name; // string\n * }, userSchema);\n * ```\n */\nexport function schema<T extends SchemaDefinition>(definition: T): T {\n  return definition;\n}\n\n/**\n * Converts a JSON Schema definition to internal schema format\n * @template T - JSON Schema definition type\n * @param definition - JSON Schema definition object\n * @returns Converted schema definition with preserved types\n *\n * @example\n * ```typescript\n * import { schema } from 'kitojs';\n *\n * const userSchema = schema.json({\n *   params: {\n *     type: 'object',\n *     properties: {\n *       id: { type: 'string', format: 'uuid' }\n *     },\n *     required: ['id']\n *   },\n *   body: {\n *     type: 'object',\n *     properties: {\n *       name: { type: 'string', minLength: 1 },\n *       email: { type: 'string', format: 'email' }\n *     },\n *     required: ['name', 'email']\n *   }\n * });\n *\n * app.post('/users/:id', ({ req, res }) => {\n *   // types are inferred from JSON Schema\n *   const id = req.params.id; // string\n *   const name = req.body.name; // string\n * }, userSchema);\n * ```\n */\nschema.json = <T extends JSONSchemaDefinition>(\n  definition: T,\n): SchemaDefinition & {\n  __jsonSchemaInfer: InferJSONSchemaRequest<T>;\n} => {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  const converted: any = {};\n\n  if (definition.params) {\n    converted.params = convertJSONSchema(definition.params);\n  }\n  if (definition.query) {\n    converted.query = convertJSONSchema(definition.query);\n  }\n  if (definition.body) {\n    converted.body = convertJSONSchema(definition.body);\n  }\n  if (definition.headers) {\n    converted.headers = convertJSONSchema(definition.headers);\n  }\n  if (definition.response) {\n    converted.response = {};\n    for (const [statusCode, responseSchema] of Object.entries(\n      definition.response,\n    )) {\n      converted.response[statusCode] = convertJSONSchema(responseSchema);\n    }\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  return converted as any;\n};\n"
  },
  {
    "path": "packages/kitojs/src/index.ts",
    "content": "/**\n * @module kitojs\n *\n * Kito is a high-performance, type-safe TypeScript web framework with a Rust core.\n *\n * @example Basic usage\n * ```typescript\n * import { server } from 'kitojs';\n *\n * const app = server();\n *\n * app.get('/', ctx => {\n *   ctx.res.send('Hello World!');\n * });\n *\n * app.listen(3000);\n * ```\n *\n * @example With schema validation\n * ```typescript\n * import { server, schema, t } from 'kitojs';\n *\n * const userSchema = schema({\n *   params: t.object({ id: t.str().uuid() }),\n *   body: t.object({\n *     name: t.str().min(1),\n *     email: t.str().email()\n *   })\n * });\n *\n * app.post('/users/:id', [userSchema], ctx => {\n *   ctx.res.json({\n *     id: ctx.req.params.id,\n *     ...ctx.req.body\n *   });\n * });\n * ```\n *\n * @example With middleware\n * ```typescript\n * import { server, middleware } from 'kitojs';\n *\n * const logger = middleware((ctx, next) => {\n *   console.log(`${ctx.req.method} ${ctx.req.url}`);\n *   next();\n * });\n *\n * app.use(logger);\n * ```\n *\n * @example With context extensions\n * ```typescript\n * const app = server().extend<{ db: Database }>(ctx => {\n *   ctx.db = createDatabase();\n * });\n *\n * app.get('/users', async ctx => {\n *   const users = await ctx.db.query('SELECT * FROM users');\n *   ctx.res.json(users);\n * });\n * ```\n *\n * @example With routers\n * ```typescript\n * import { server, router } from 'kitojs';\n *\n * const apiRouter = router();\n * apiRouter.get('/users', ({ res }) => res.json({ users: [] }));\n *\n * const app = server();\n * app.mount('/api', apiRouter);\n * app.listen(3000);\n * ```\n */\n\n// biome-ignore assist/source/organizeImports: ...\nexport * from \"./schemas/builders\";\n\nexport * from \"./helpers/schema\";\nexport * from \"./helpers/middleware\";\n\nexport * from \"./server/server\";\nexport * from \"./server/router\";\nexport * from \"./types\";\n"
  },
  {
    "path": "packages/kitojs/src/schemas/builders.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport { StringSchemaImpl } from \"./primitives/string\";\nimport { NumberSchemaImpl } from \"./primitives/number\";\nimport { BooleanSchemaImpl } from \"./primitives/boolean\";\nimport { ArraySchemaImpl } from \"./primitives/array\";\nimport { ObjectSchemaImpl } from \"./primitives/object\";\nimport { LiteralSchemaImpl } from \"./primitives/literal\";\nimport { UnionSchemaImpl } from \"./primitives/union\";\n\nimport type {\n  StringSchema,\n  NumberSchema,\n  BooleanSchema,\n  ArraySchema,\n  ObjectSchema,\n  LiteralSchema,\n  UnionSchema,\n  SchemaType,\n} from \"@kitojs/types\";\n\n/**\n * Schema builder utilities for creating type-safe request validation schemas.\n *\n * @example\n * ```typescript\n * import { t, schema } from 'kitojs';\n *\n * const userSchema = schema({\n *   params: t.object({\n *     id: t.str().uuid()\n *   }),\n *   body: t.object({\n *     name: t.str().min(1).max(50),\n *     email: t.str().email(),\n *     age: t.num().min(0).optional()\n *   })\n * });\n *\n * app.post('/users/:id', [userSchema], ctx => {\n *   // ctx.req.params.id is validated as UUID\n *   // ctx.req.body is type-safe and validated\n * });\n * ```\n */\nexport const t = {\n  /**\n   * Creates a string schema builder.\n   *\n   * @returns String schema with validation methods\n   *\n   * @example\n   * ```typescript\n   * t.str() // basic string\n   * t.str().min(3).max(50) // length constraints\n   * t.str().email() // email validation\n   * t.str().uuid() // UUID validation\n   * t.str().optional() // optional field\n   * t.str().default('hello') // default value\n   * ```\n   */\n  str(): StringSchema {\n    return new StringSchemaImpl();\n  },\n\n  /**\n   * Creates a number schema builder.\n   *\n   * @returns Number schema with validation methods\n   *\n   * @example\n   * ```typescript\n   * t.num() // basic number\n   * t.num().min(0).max(100) // range constraints\n   * t.num().int() // integer only\n   * t.num().positive() // positive numbers\n   * t.num().optional() // optional field\n   * t.num().default(0) // default value\n   * ```\n   */\n  num(): NumberSchema {\n    return new NumberSchemaImpl();\n  },\n\n  /**\n   * Creates a boolean schema builder.\n   *\n   * @returns Boolean schema with validation methods\n   *\n   * @example\n   * ```typescript\n   * t.bool() // basic boolean\n   * t.bool().optional() // optional field\n   * t.bool().default(false) // default value\n   * ```\n   */\n  bool(): BooleanSchema {\n    return new BooleanSchemaImpl();\n  },\n\n  /**\n   * Creates an array schema builder.\n   *\n   * @template T - Type of array items\n   * @param item - Schema for array items\n   * @returns Array schema with validation methods\n   *\n   * @example\n   * ```typescript\n   * t.array(t.str()) // string array\n   * t.array(t.num().positive()) // array of positive numbers\n   * t.array(t.object({ name: t.str() })) // array of objects\n   * t.array(t.str()).min(1).max(10) // length constraints\n   * ```\n   */\n  array<T extends SchemaType>(item: T): ArraySchema<T> {\n    return new ArraySchemaImpl(item);\n  },\n\n  /**\n   * Creates an object schema builder.\n   *\n   * @template T - Object shape definition\n   * @param shape - Object property schemas\n   * @returns Object schema with validation methods\n   *\n   * @example\n   * ```typescript\n   * t.object({\n   *   name: t.str(),\n   *   age: t.num(),\n   *   email: t.str().email().optional()\n   * })\n   *\n   * // Nested objects\n   * t.object({\n   *   user: t.object({\n   *     profile: t.object({\n   *       bio: t.str()\n   *     })\n   *   })\n   * })\n   * ```\n   */\n  object<T extends Record<string, SchemaType>>(shape: T): ObjectSchema<T> {\n    return new ObjectSchemaImpl(shape);\n  },\n\n  /**\n   * Creates a literal schema for exact value matching.\n   *\n   * @template T - Literal value type\n   * @param value - Exact value to match\n   * @returns Literal schema\n   *\n   * @example\n   * ```typescript\n   * t.literal('admin') // matches only \"admin\"\n   * t.literal(42) // matches only 42\n   * t.literal(true) // matches only true\n   * ```\n   */\n  literal<T extends string | number | boolean>(value: T): LiteralSchema<T> {\n    return new LiteralSchemaImpl(value);\n  },\n\n  /**\n   * Creates a union schema for multiple possible types.\n   *\n   * @template T - Array of possible schema types\n   * @param schemas - Schemas to union\n   * @returns Union schema\n   *\n   * @example\n   * ```typescript\n   * // String or number\n   * t.union(t.str(), t.num())\n   *\n   * // Enum-like literals\n   * t.union(\n   *   t.literal('admin'),\n   *   t.literal('user'),\n   *   t.literal('guest')\n   * )\n   *\n   * // Complex types\n   * t.union(\n   *   t.object({ type: t.literal('user'), name: t.str() }),\n   *   t.object({ type: t.literal('guest') })\n   * )\n   * ```\n   */\n  union<T extends SchemaType[]>(...schemas: T): UnionSchema<T> {\n    return new UnionSchemaImpl(schemas);\n  },\n};\n"
  },
  {
    "path": "packages/kitojs/src/schemas/index.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nexport * from \"./builders\";\n\nexport * from \"./primitives/string\";\nexport * from \"./primitives/number\";\nexport * from \"./primitives/boolean\";\nexport * from \"./primitives/array\";\nexport * from \"./primitives/object\";\nexport * from \"./primitives/literal\";\nexport * from \"./primitives/union\";\n"
  },
  {
    "path": "packages/kitojs/src/schemas/jsonSchema.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  SchemaType,\n  JSONSchema,\n  JSONSchemaString,\n  JSONSchemaNumber,\n  JSONSchemaBoolean,\n  JSONSchemaArray,\n  JSONSchemaObject,\n} from \"@kitojs/types\";\n\nimport { t } from \"./builders\";\n\nexport function convertJSONSchema(schema: JSONSchema): SchemaType {\n  switch (schema.type) {\n    case \"string\":\n      return convertStringSchema(schema as JSONSchemaString);\n    case \"number\":\n    case \"integer\":\n      return convertNumberSchema(schema as JSONSchemaNumber);\n    case \"boolean\":\n      return convertBooleanSchema(schema as JSONSchemaBoolean);\n    case \"array\":\n      return convertArraySchema(schema as JSONSchemaArray);\n    case \"object\":\n      return convertObjectSchema(schema as JSONSchemaObject);\n    default:\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      throw new Error(`Unsupported JSON Schema type: ${(schema as any).type}`);\n  }\n}\n\nfunction convertStringSchema(schema: JSONSchemaString): SchemaType {\n  if (schema.const !== undefined) {\n    let schemaBuilder = t.literal(schema.const);\n    if (schema.default !== undefined) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      schemaBuilder = schemaBuilder.default(schema.default as string) as any;\n    }\n    return schemaBuilder as SchemaType;\n  }\n\n  if (schema.enum && schema.enum.length > 0) {\n    const literals = schema.enum.map((value) => t.literal(value));\n    let schemaBuilder = t.union(...literals);\n    if (schema.default !== undefined) {\n      schemaBuilder = schemaBuilder.default(\n        schema.default as (typeof schema.enum)[number],\n        // biome-ignore lint/suspicious/noExplicitAny: ...\n      ) as any;\n    }\n    return schemaBuilder as SchemaType;\n  }\n\n  let schemaBuilder = t.str();\n\n  if (schema.minLength !== undefined) {\n    schemaBuilder = schemaBuilder.min(schema.minLength);\n  }\n  if (schema.maxLength !== undefined) {\n    schemaBuilder = schemaBuilder.max(schema.maxLength);\n  }\n\n  if (schema.format) {\n    switch (schema.format) {\n      case \"email\":\n        schemaBuilder = schemaBuilder.email();\n        break;\n      case \"uuid\":\n        schemaBuilder = schemaBuilder.uuid();\n        break;\n      case \"uri\":\n        schemaBuilder = schemaBuilder.url();\n        break;\n    }\n  }\n\n  if (schema.pattern) {\n    schemaBuilder = schemaBuilder.regex(new RegExp(schema.pattern));\n  }\n\n  if (schema.default !== undefined) {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    schemaBuilder = schemaBuilder.default(schema.default as string) as any;\n  }\n\n  return schemaBuilder as SchemaType;\n}\n\nfunction convertNumberSchema(schema: JSONSchemaNumber): SchemaType {\n  if (schema.const !== undefined) {\n    let schemaBuilder = t.literal(schema.const);\n    if (schema.default !== undefined) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      schemaBuilder = schemaBuilder.default(schema.default as number) as any;\n    }\n    return schemaBuilder as SchemaType;\n  }\n\n  if (schema.enum && schema.enum.length > 0) {\n    const literals = schema.enum.map((value) => t.literal(value));\n    let schemaBuilder = t.union(...literals);\n    if (schema.default !== undefined) {\n      schemaBuilder = schemaBuilder.default(\n        schema.default as (typeof schema.enum)[number],\n        // biome-ignore lint/suspicious/noExplicitAny: ...\n      ) as any;\n    }\n    return schemaBuilder as SchemaType;\n  }\n\n  let schemaBuilder = t.num();\n\n  if (schema.type === \"integer\") {\n    schemaBuilder = schemaBuilder.int();\n  }\n\n  if (schema.minimum !== undefined) {\n    schemaBuilder = schemaBuilder.min(schema.minimum);\n  }\n  if (schema.maximum !== undefined) {\n    schemaBuilder = schemaBuilder.max(schema.maximum);\n  }\n\n  if (schema.default !== undefined) {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    schemaBuilder = schemaBuilder.default(schema.default as number) as any;\n  }\n\n  return schemaBuilder as SchemaType;\n}\n\nfunction convertBooleanSchema(schema: JSONSchemaBoolean): SchemaType {\n  if (schema.const !== undefined) {\n    let schemaBuilder = t.literal(schema.const);\n    if (schema.default !== undefined) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      schemaBuilder = schemaBuilder.default(schema.default as boolean) as any;\n    }\n    return schemaBuilder as SchemaType;\n  }\n\n  let schemaBuilder = t.bool();\n\n  if (schema.default !== undefined) {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    schemaBuilder = schemaBuilder.default(schema.default as boolean) as any;\n  }\n\n  return schemaBuilder as SchemaType;\n}\n\nfunction convertArraySchema(schema: JSONSchemaArray): SchemaType {\n  const itemSchema = convertJSONSchema(schema.items);\n\n  let schemaBuilder = t.array(itemSchema);\n\n  if (schema.minItems !== undefined) {\n    schemaBuilder = schemaBuilder.min(schema.minItems);\n  }\n  if (schema.maxItems !== undefined) {\n    schemaBuilder = schemaBuilder.max(schema.maxItems);\n  }\n\n  if (schema.default !== undefined) {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    schemaBuilder = schemaBuilder.default(schema.default as any[]) as any;\n  }\n\n  return schemaBuilder as SchemaType;\n}\n\nfunction convertObjectSchema(schema: JSONSchemaObject): SchemaType {\n  const shape: Record<string, SchemaType> = {};\n  const requiredFields = new Set(schema.required || []);\n\n  for (const [key, propSchema] of Object.entries(schema.properties)) {\n    let convertedSchema = convertJSONSchema(propSchema);\n\n    if (!requiredFields.has(key)) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      convertedSchema = (convertedSchema as any).optional();\n    }\n\n    shape[key] = convertedSchema;\n  }\n\n  let schemaBuilder = t.object(shape);\n\n  if (schema.default !== undefined && schema.default !== null) {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    schemaBuilder = schemaBuilder.default(schema.default as any) as any;\n  }\n\n  return schemaBuilder as SchemaType;\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/array.ts",
    "content": "import type { ArraySchema, SchemaType } from \"@kitojs/types\";\n\nexport class ArraySchemaImpl<T extends SchemaType> implements ArraySchema<T> {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  _type!: any[];\n  _optional = false;\n  _default: unknown = undefined;\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private constraints: any[] = [];\n\n  constructor(private item: T) {}\n\n  min(length: number): ArraySchema<T> {\n    this.constraints.push({ type: \"min\", value: length });\n    return this;\n  }\n\n  max(length: number): ArraySchema<T> {\n    this.constraints.push({ type: \"max\", value: length });\n    return this;\n  }\n\n  length(length: number): ArraySchema<T> {\n    this.constraints.push({ type: \"length\", value: length });\n    return this;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: any[]): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"array\",\n      optional: this._optional,\n      default: this._default,\n      constraints: this.constraints,\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      item: (this.item as any)._serialize(),\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/boolean.ts",
    "content": "import type { BooleanSchema } from \"@kitojs/types\";\n\nexport class BooleanSchemaImpl implements BooleanSchema {\n  _type!: boolean;\n  _optional = false;\n  _default: unknown = undefined;\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: boolean): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"boolean\",\n      optional: this._optional,\n      default: this._default,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/literal.ts",
    "content": "import type { LiteralSchema } from \"@kitojs/types\";\n\nexport class LiteralSchemaImpl<T extends string | number | boolean>\n  implements LiteralSchema<T>\n{\n  _type!: T;\n  _optional = false;\n  _default: unknown = undefined;\n\n  constructor(private value: T) {}\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: T): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"literal\",\n      optional: this._optional,\n      default: this._default,\n      value: this.value,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/number.ts",
    "content": "import type { NumberSchema } from \"@kitojs/types\";\n\nexport class NumberSchemaImpl implements NumberSchema {\n  _type!: number;\n  _optional = false;\n  _default: unknown = undefined;\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private constraints: any[] = [];\n\n  min(value: number): NumberSchema {\n    this.constraints.push({ type: \"min\", value });\n    return this;\n  }\n\n  max(value: number): NumberSchema {\n    this.constraints.push({ type: \"max\", value });\n    return this;\n  }\n\n  int(): NumberSchema {\n    this.constraints.push({ type: \"int\" });\n    return this;\n  }\n\n  positive(): NumberSchema {\n    this.constraints.push({ type: \"positive\" });\n    return this;\n  }\n\n  negative(): NumberSchema {\n    this.constraints.push({ type: \"negative\" });\n    return this;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: number): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"number\",\n      optional: this._optional,\n      default: this._default,\n      constraints: this.constraints,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/object.ts",
    "content": "import type { InferType, ObjectSchema, SchemaType } from \"@kitojs/types\";\n\nexport class ObjectSchemaImpl<T extends Record<string, SchemaType>>\n  implements ObjectSchema<T>\n{\n  _type!: { [K in keyof T]: InferType<T[K]> };\n  _optional = false;\n  _default: unknown = undefined;\n  shape: T;\n\n  constructor(shape: T) {\n    this.shape = shape;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: any): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    const shape: any = {};\n    for (const [key, schema] of Object.entries(this.shape)) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      shape[key] = (schema as any)._serialize();\n    }\n    return {\n      type: \"object\",\n      optional: this._optional,\n      default: this._default,\n      shape,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/string.ts",
    "content": "import type { StringSchema } from \"@kitojs/types\";\n\nexport class StringSchemaImpl implements StringSchema {\n  _type!: string;\n  _optional = false;\n  _default: unknown = undefined;\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private constraints: any[] = [];\n\n  min(length: number): StringSchema {\n    this.constraints.push({ type: \"min\", value: length });\n    return this;\n  }\n\n  max(length: number): StringSchema {\n    this.constraints.push({ type: \"max\", value: length });\n    return this;\n  }\n\n  length(length: number): StringSchema {\n    this.constraints.push({ type: \"length\", value: length });\n    return this;\n  }\n\n  email(): StringSchema {\n    this.constraints.push({ type: \"email\" });\n    return this;\n  }\n\n  url(): StringSchema {\n    this.constraints.push({ type: \"url\" });\n    return this;\n  }\n\n  uuid(): StringSchema {\n    this.constraints.push({ type: \"uuid\" });\n    return this;\n  }\n\n  regex(pattern: RegExp): StringSchema {\n    this.constraints.push({ type: \"regex\", value: pattern });\n    return this;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: string): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"string\",\n      optional: this._optional,\n      default: this._default,\n      constraints: this.constraints,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/schemas/primitives/union.ts",
    "content": "import type { SchemaType, UnionSchema } from \"@kitojs/types\";\n\nexport class UnionSchemaImpl<T extends SchemaType[]> implements UnionSchema<T> {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  _type!: any;\n  _optional = false;\n  _default: unknown = undefined;\n\n  constructor(private schemas: T) {}\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  optional(): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    return clone;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  default(value: any): any {\n    const clone = Object.assign(\n      Object.create(Object.getPrototypeOf(this)),\n      this,\n    );\n    clone._optional = true;\n    clone._default = value;\n    return clone;\n  }\n\n  _serialize() {\n    return {\n      type: \"union\",\n      optional: this._optional,\n      default: this._default,\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      schemas: this.schemas.map((s) => (s as any)._serialize()),\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/server/analyzer.ts",
    "content": "import * as acorn from \"acorn\";\nimport * as walk from \"acorn-walk\";\n\nexport type StaticResponseType =\n  | { type: \"none\" }\n  | {\n      type: \"full_static\";\n      method: string;\n      status: number;\n      headers: Record<string, string>;\n      body: string;\n    }\n  | {\n      type: \"param_template\";\n      method: string;\n      status: number;\n      headers: Record<string, string>;\n      template: string;\n      params: string[];\n    };\n\ninterface ResponseCall {\n  method: \"send\" | \"json\" | \"text\" | \"html\";\n  arg?: any;\n  usesContext: boolean;\n}\n\nexport function analyzeHandler(handler: Function): StaticResponseType {\n  const source = handler.toString();\n\n  try {\n    const ast = acorn.parse(source, {\n      ecmaVersion: 2022,\n      sourceType: \"module\",\n    }) as any;\n\n    let responseCall: ResponseCall | null = null;\n    let hasLogic = false;\n\n    const usedParams = new Set<string>();\n    const usedQuery = new Set<string>();\n\n    walk.simple(ast, {\n      CallExpression(node: any) {\n        if (\n          node.callee.type === \"MemberExpression\" &&\n          node.callee.object.type === \"MemberExpression\" &&\n          node.callee.object.property.name === \"res\"\n        ) {\n          const method = node.callee.property.name;\n\n          if ([\"send\", \"json\", \"text\", \"html\"].includes(method)) {\n            if (responseCall !== null) {\n              hasLogic = true;\n              return;\n            }\n\n            const newResponseCall: ResponseCall = {\n              method,\n              arg: node.arguments[0],\n              usesContext: false,\n            };\n\n            walk.simple(node.arguments[0], {\n              MemberExpression(argNode: any) {\n                if (\n                  argNode.object.type === \"Identifier\" &&\n                  argNode.object.name === \"ctx\"\n                ) {\n                  newResponseCall.usesContext = true;\n                }\n              },\n            });\n\n            responseCall = newResponseCall;\n          }\n        }\n      },\n\n      MemberExpression(node: any) {\n        if (\n          node.object.type === \"MemberExpression\" &&\n          node.object.object.type === \"MemberExpression\" &&\n          node.object.object.property.name === \"req\" &&\n          node.object.property.name === \"params\"\n        ) {\n          if (node.property.type === \"Identifier\") {\n            usedParams.add(node.property.name);\n          }\n        }\n\n        if (\n          node.object.type === \"MemberExpression\" &&\n          node.object.object.type === \"MemberExpression\" &&\n          node.object.object.property.name === \"req\" &&\n          node.object.property.name === \"query\"\n        ) {\n          if (node.property.type === \"Identifier\") {\n            usedQuery.add(node.property.name);\n          }\n        }\n      },\n\n      VariableDeclaration() {\n        hasLogic = true;\n      },\n\n      IfStatement() {\n        hasLogic = true;\n      },\n      ForStatement() {\n        hasLogic = true;\n      },\n      WhileStatement() {\n        hasLogic = true;\n      },\n    });\n\n    if (!responseCall) {\n      return { type: \"none\" };\n    }\n\n    const rc = responseCall as ResponseCall;\n\n    if (hasLogic) {\n      return { type: \"none\" };\n    }\n\n    if (!rc.usesContext) {\n      const value = evaluateStaticValue(rc.arg, source);\n      if (value === null) {\n        return { type: \"none\" };\n      }\n\n      const { body, contentType } = serializeResponseValue(rc.method, value);\n\n      return {\n        type: \"full_static\",\n        method: rc.method,\n        status: 200,\n        headers: {\n          \"content-type\": contentType,\n          \"content-length\": body.length.toString(),\n        },\n        body: body.toString(\"base64\"),\n      };\n    }\n\n    if (usedParams.size > 0 || usedQuery.size > 0) {\n      if (rc.method === \"json\" && rc.arg?.type === \"ObjectExpression\") {\n        const template = extractTemplate(rc.arg);\n        return {\n          type: \"param_template\",\n          method: \"json\",\n          status: 200,\n          headers: {\n            \"content-type\": \"application/json\",\n          },\n          template,\n          params: Array.from(usedParams),\n        };\n      }\n    }\n\n    return { type: \"none\" };\n  } catch (error) {\n    console.warn(\"Failed to analyze handler:\", error);\n    return { type: \"none\" };\n  }\n}\n\nfunction evaluateStaticValue(node: any, source: string): any {\n  if (!node) return null;\n\n  try {\n    switch (node.type) {\n      case \"Literal\":\n        return node.value;\n\n      case \"ObjectExpression\":\n        const obj: any = {};\n        for (const prop of node.properties) {\n          if (prop.type === \"Property\" && prop.key.type === \"Identifier\") {\n            const value = evaluateStaticValue(prop.value, source);\n            if (value === null) return null;\n            obj[prop.key.name] = value;\n          }\n        }\n        return obj;\n\n      case \"ArrayExpression\":\n        const arr: any[] = [];\n        for (const element of node.elements) {\n          const value = evaluateStaticValue(element, source);\n          if (value === null) return null;\n          arr.push(value);\n        }\n        return arr;\n\n      case \"TemplateLiteral\":\n        if (node.expressions.length === 0) {\n          return node.quasis[0].value.cooked;\n        }\n        return null;\n\n      default:\n        return null;\n    }\n  } catch {\n    return null;\n  }\n}\n\nfunction serializeResponseValue(\n  method: string,\n  value: any,\n): { body: Buffer; contentType: string } {\n  switch (method) {\n    case \"json\":\n      return {\n        body: Buffer.from(JSON.stringify(value), \"utf-8\"),\n        contentType: \"application/json\",\n      };\n    case \"text\":\n    case \"send\":\n      return {\n        body: Buffer.from(String(value), \"utf-8\"),\n        contentType: \"text/plain\",\n      };\n    case \"html\":\n      return {\n        body: Buffer.from(String(value), \"utf-8\"),\n        contentType: \"text/html\",\n      };\n    default:\n      return {\n        body: Buffer.from(String(value), \"utf-8\"),\n        contentType: \"text/plain\",\n      };\n  }\n}\n\nfunction extractTemplate(node: any): string {\n  const parts: string[] = [];\n\n  function processNode(n: any): string {\n    if (n.type === \"Literal\") return JSON.stringify(n.value);\n    if (\n      n.type === \"MemberExpression\" &&\n      n.object.type === \"MemberExpression\" &&\n      n.object.object.type === \"MemberExpression\" &&\n      n.object.object.property.name === \"req\"\n    ) {\n      const source = n.object.property.name;\n      const key = n.property.name;\n      return `\"{{${source}.${key}}}\"`;\n    }\n    return \"null\";\n  }\n\n  const props = node.properties.map((prop: any) => {\n    const key = prop.key.name;\n    const value = processNode(prop.value);\n    return `\"${key}\":${value}`;\n  });\n\n  return `{${props.join(\",\")}}`;\n}\n"
  },
  {
    "path": "packages/kitojs/src/server/request.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  CommonHeaderNames,\n  KitoRequest,\n  RequestHeaders,\n} from \"@kitojs/types\";\nimport {\n  getBodyBuffer,\n  getHeader,\n  getAllHeaders,\n  getQueryParam,\n  getAllQuery,\n  getParam,\n  getAllParams,\n  getCookie,\n  getAllCookies,\n  getMethod,\n  getUrl,\n  getPathname,\n  getSearch,\n  getProtocol,\n  getHostname,\n  getIp,\n  getIps,\n  getSecure,\n  getXhr,\n} from \"@kitojs/kito-core\";\n\nexport class RequestBuilder implements KitoRequest {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private core: any;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  private _body?: Buffer | JSON | {};\n  private _headers?: Record<string, string>;\n  private _query?: Record<string, string | string[]>;\n  private _params?: Record<string, string>;\n  private _cookies?: Record<string, string>;\n  private _method?: string;\n  private _url?: string;\n  private _pathname?: string;\n  private _search?: string | null;\n  private _protocol?: string;\n  private _hostname?: string;\n  private _ip?: string;\n  private _ips?: string[];\n  private _secure?: boolean;\n  private _xhr?: boolean;\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  constructor(requestCore: any) {\n    this.core = requestCore;\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  get body(): any {\n    if (this._body) return this._body;\n\n    const buf = getBodyBuffer(this.core);\n    const type = this.header(\"content-type\") ?? \"\";\n\n    if (type.includes(\"application/json\")) {\n      try {\n        this._body = JSON.parse(buf.toString(\"utf-8\"));\n      } catch {\n        this._body = {};\n      }\n    } else {\n      this._body = buf;\n    }\n\n    return this._body;\n  }\n\n  json<T = unknown>(): T {\n    if (typeof this.body === \"object\" && !Buffer.isBuffer(this.body)) {\n      return this.body as T;\n    }\n\n    if (Buffer.isBuffer(this.body)) {\n      return JSON.parse(this.body.toString(\"utf-8\")) as T;\n    }\n\n    if (typeof this.body === \"string\") {\n      return JSON.parse(this.body) as T;\n    }\n\n    return this.body as T;\n  }\n\n  text(): string {\n    if (Buffer.isBuffer(this.body)) {\n      return this.body.toString(\"utf-8\");\n    }\n\n    return String(this.body);\n  }\n\n  get headers(): RequestHeaders {\n    if (!this._headers) {\n      this._headers = getAllHeaders(this.core);\n    }\n    return this._headers;\n  }\n\n  header(name: CommonHeaderNames): string | undefined;\n  header(name: string): string | undefined;\n  header(name: string): string | undefined {\n    const value = getHeader(this.core, name.toLowerCase());\n    return value ?? undefined;\n  }\n\n  get query(): Record<string, string | string[]> {\n    if (!this._query) {\n      this._query = getAllQuery(this.core);\n    }\n    return this._query;\n  }\n\n  queryParam(name: string): string | string[] | undefined {\n    const value = getQueryParam(this.core, name);\n    if (!value) return undefined;\n    return value.length === 1 ? value[0] : value;\n  }\n\n  get params(): Record<string, string> {\n    if (!this._params) {\n      this._params = getAllParams(this.core);\n    }\n    return this._params;\n  }\n\n  param(name: string): string | undefined {\n    return getParam(this.core, name) ?? undefined;\n  }\n\n  get cookies(): Record<string, string> {\n    if (!this._cookies) {\n      this._cookies = getAllCookies(this.core);\n    }\n    return this._cookies;\n  }\n\n  cookie(name: string): string | undefined {\n    return getCookie(this.core, name) ?? undefined;\n  }\n\n  get method(): string {\n    if (!this._method) {\n      this._method = getMethod(this.core);\n    }\n    return this._method;\n  }\n\n  get url(): string {\n    if (!this._url) {\n      this._url = getUrl(this.core);\n    }\n    return this._url;\n  }\n\n  get pathname(): string {\n    if (!this._pathname) {\n      this._pathname = getPathname(this.core);\n    }\n    return this._pathname;\n  }\n\n  get search(): string | null {\n    if (this._search === undefined) {\n      this._search = getSearch(this.core) ?? null;\n    }\n    return this._search;\n  }\n\n  get protocol(): string {\n    if (!this._protocol) {\n      this._protocol = getProtocol(this.core);\n    }\n    return this._protocol;\n  }\n\n  get hostname(): string {\n    if (!this._hostname) {\n      this._hostname = getHostname(this.core);\n    }\n    return this._hostname;\n  }\n\n  get ip(): string {\n    if (!this._ip) {\n      this._ip = getIp(this.core);\n    }\n    return this._ip;\n  }\n\n  get ips(): string[] {\n    if (!this._ips) {\n      this._ips = getIps(this.core);\n    }\n    return this._ips;\n  }\n\n  get secure(): boolean {\n    if (this._secure === undefined) {\n      this._secure = getSecure(this.core);\n    }\n    return this._secure;\n  }\n\n  get xhr(): boolean {\n    if (this._xhr === undefined) {\n      this._xhr = getXhr(this.core);\n    }\n    return this._xhr;\n  }\n\n  get originalUrl(): string {\n    return this.url;\n  }\n\n  get raw(): {\n    body: Buffer;\n    headers: RequestHeaders;\n    url: string;\n    method: string;\n  } {\n    return {\n      body: this.body,\n      headers: this.headers,\n      url: this.url,\n      method: this.method,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/server/response.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  KitoResponse,\n  CookieOptions,\n  SendFileOptions,\n  CommonResponseHeaderNames,\n  StreamWriter,\n  SSEWriter,\n} from \"@kitojs/types\";\n\nimport {\n  sendResponse,\n  startStream,\n  sendChunk,\n  endStream,\n} from \"@kitojs/kito-core\";\nimport { readFileSync, statSync } from \"node:fs\";\n\nconst HTTP_STATUS_MESSAGES: Record<number, string> = {\n  100: \"Continue\",\n  101: \"Switching Protocols\",\n  200: \"OK\",\n  201: \"Created\",\n  202: \"Accepted\",\n  204: \"No Content\",\n  301: \"Moved Permanently\",\n  302: \"Found\",\n  304: \"Not Modified\",\n  400: \"Bad Request\",\n  401: \"Unauthorized\",\n  403: \"Forbidden\",\n  404: \"Not Found\",\n  405: \"Method Not Allowed\",\n  500: \"Internal Server Error\",\n  502: \"Bad Gateway\",\n  503: \"Service Unavailable\",\n};\n\ninterface ResponseState {\n  status: number;\n  headers: Map<string, string>;\n  body?: Buffer;\n  streaming: boolean;\n}\n\nclass StreamWriterImpl implements StreamWriter {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  constructor(private channel: any) {}\n\n  write(data: string | Buffer): void {\n    const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, \"utf-8\");\n    sendChunk(this.channel, buffer);\n  }\n\n  end(data?: string | Buffer): void {\n    if (data !== undefined) {\n      this.write(data);\n    }\n\n    endStream(this.channel);\n  }\n}\n\nclass SSEWriterImpl implements SSEWriter {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  constructor(private channel: any) {}\n\n  send(data: unknown, event?: string, id?: string, retry?: number): void {\n    let message = \"\";\n\n    if (event) {\n      message += `event: ${event}\\n`;\n    }\n\n    if (id) {\n      message += `id: ${id}\\n`;\n    }\n\n    if (retry !== undefined) {\n      message += `retry: ${retry}\\n`;\n    }\n\n    const dataStr = typeof data === \"string\" ? data : JSON.stringify(data);\n    const lines = dataStr.split(\"\\n\");\n\n    for (const line of lines) {\n      message += `data: ${line}\\n`;\n    }\n\n    message += \"\\n\";\n\n    sendChunk(this.channel, Buffer.from(message, \"utf-8\"));\n  }\n\n  comment(text: string): void {\n    const message = `: ${text}\\n\\n`;\n    sendChunk(this.channel, Buffer.from(message, \"utf-8\"));\n  }\n\n  close(): void {\n    endStream(this.channel);\n  }\n}\n\nexport class ResponseBuilder implements KitoResponse {\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private channel: any;\n  private state: ResponseState;\n  private finished = false;\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  constructor(responseChannel: any) {\n    this.channel = responseChannel;\n    this.state = {\n      status: 200,\n      headers: new Map(),\n      streaming: false,\n    };\n  }\n\n  private checkFinished(): void {\n    if (this.finished) {\n      throw new Error(\"Response already sent\");\n    }\n  }\n\n  private serializeAndSend(): void {\n    const headersArray = Array.from(this.state.headers.entries());\n    const headersJson = JSON.stringify(headersArray);\n    const headersBytes = Buffer.from(headersJson, \"utf-8\");\n\n    const body = this.state.body || Buffer.alloc(0);\n\n    const totalSize = 2 + 4 + headersBytes.length + body.length;\n    const buffer = Buffer.allocUnsafe(totalSize);\n\n    let offset = 0;\n\n    buffer.writeUInt16LE(this.state.status, offset);\n    offset += 2;\n\n    buffer.writeUInt32LE(headersBytes.length, offset);\n    offset += 4;\n\n    headersBytes.copy(buffer, offset);\n    offset += headersBytes.length;\n\n    if (body.length > 0) {\n      body.copy(buffer, offset);\n    }\n\n    sendResponse(this.channel, buffer);\n    this.finished = true;\n  }\n\n  private startStreamingResponse(): void {\n    const headersArray = Array.from(this.state.headers.entries());\n    const headersJson = JSON.stringify(headersArray);\n    const headersBytes = Buffer.from(headersJson, \"utf-8\");\n\n    const totalSize = 2 + 4 + headersBytes.length;\n    const buffer = Buffer.allocUnsafe(totalSize);\n\n    let offset = 0;\n\n    buffer.writeUInt16LE(this.state.status, offset);\n    offset += 2;\n\n    buffer.writeUInt32LE(headersBytes.length, offset);\n    offset += 4;\n\n    headersBytes.copy(buffer, offset);\n\n    startStream(this.channel, buffer);\n    this.state.streaming = true;\n    this.finished = true;\n  }\n\n  status(code: number): KitoResponse {\n    this.checkFinished();\n    this.state.status = code;\n    return this;\n  }\n\n  sendStatus(code: number): void {\n    this.checkFinished();\n    const message = HTTP_STATUS_MESSAGES[code] || \"Unknown\";\n    this.state.status = code;\n    this.state.body = Buffer.from(message, \"utf-8\");\n    this.serializeAndSend();\n  }\n\n  header(name: CommonResponseHeaderNames, value: string): KitoResponse;\n  header(name: string, value: string): KitoResponse;\n  header(name: string, value: string): KitoResponse {\n    this.checkFinished();\n\n    this.state.headers.set(name.toLowerCase(), value);\n    return this;\n  }\n\n  headers(headers: Record<CommonResponseHeaderNames, string>): KitoResponse;\n  headers(headers: Record<string, string>): KitoResponse;\n  headers(headers: Record<string, string>): KitoResponse {\n    this.checkFinished();\n\n    for (const [name, value] of Object.entries(headers)) {\n      this.state.headers.set(name.toLowerCase(), value);\n    }\n    return this;\n  }\n\n  append(field: CommonResponseHeaderNames, value: string): KitoResponse;\n  append(field: string, value: string): KitoResponse;\n  append(field: string, value: string): KitoResponse {\n    this.checkFinished();\n\n    const key = field.toLowerCase();\n    const existing = this.state.headers.get(key);\n\n    if (existing) {\n      this.state.headers.set(key, `${existing}, ${value}`);\n    } else {\n      this.state.headers.set(key, value);\n    }\n\n    return this;\n  }\n\n  set(field: CommonResponseHeaderNames, value: string): KitoResponse;\n  set(field: string, value: string): KitoResponse;\n  set(field: string, value: string): KitoResponse {\n    return this.header(field, value);\n  }\n\n  get(field: CommonResponseHeaderNames): string | undefined;\n  get(field: string): string | undefined;\n  get(field: string): string | undefined {\n    return this.state.headers.get(field.toLowerCase());\n  }\n\n  type(contentType: string): KitoResponse {\n    this.checkFinished();\n\n    if (!contentType.includes(\"/\")) {\n      const mimeTypes: Record<string, string> = {\n        html: \"text/html\",\n        json: \"application/json\",\n        xml: \"application/xml\",\n        text: \"text/plain\",\n        txt: \"text/plain\",\n        js: \"application/javascript\",\n        css: \"text/css\",\n        png: \"image/png\",\n        jpg: \"image/jpeg\",\n        jpeg: \"image/jpeg\",\n        gif: \"image/gif\",\n        svg: \"image/svg+xml\",\n        pdf: \"application/pdf\",\n        zip: \"application/zip\",\n      };\n\n      contentType = mimeTypes[contentType] || contentType;\n    }\n\n    return this.header(\"content-type\", contentType);\n  }\n\n  contentType(contentType: string): KitoResponse {\n    return this.type(contentType);\n  }\n\n  cookie(name: string, value: string, options?: CookieOptions): KitoResponse {\n    this.checkFinished();\n\n    const cookie = this.serializeCookie(name, value, options);\n\n    const existing = this.state.headers.get(\"set-cookie\");\n    if (existing) {\n      this.state.headers.set(\"set-cookie\", `${existing}, ${cookie}`);\n    } else {\n      this.state.headers.set(\"set-cookie\", cookie);\n    }\n\n    return this;\n  }\n\n  private serializeCookie(\n    name: string,\n    value: string,\n    options?: CookieOptions,\n  ): string {\n    let cookie = `${name}=${value}`;\n\n    if (options?.maxAge !== undefined) {\n      cookie += `; Max-Age=${options.maxAge}`;\n    }\n\n    if (options?.path) {\n      cookie += `; Path=${options.path}`;\n    } else {\n      cookie += \"; Path=/\";\n    }\n\n    if (options?.domain) {\n      cookie += `; Domain=${options.domain}`;\n    }\n\n    if (options?.httpOnly) {\n      cookie += \"; HttpOnly\";\n    }\n\n    if (options?.secure) {\n      cookie += \"; Secure\";\n    }\n\n    if (options?.sameSite) {\n      const sameSite =\n        typeof options.sameSite === \"string\"\n          ? options.sameSite\n          : options.sameSite\n            ? \"Strict\"\n            : \"Lax\";\n      cookie += `; SameSite=${sameSite}`;\n    }\n\n    return cookie;\n  }\n\n  clearCookie(name: string, options?: CookieOptions): KitoResponse {\n    this.checkFinished();\n\n    const clearOptions = { ...options, maxAge: 0, expires: new Date(0) };\n    return this.cookie(name, \"\", clearOptions);\n  }\n\n  // end methods\n\n  end(): void {\n    this.checkFinished();\n    this.serializeAndSend();\n  }\n\n  send(data: unknown): void {\n    this.checkFinished();\n    if (Buffer.isBuffer(data)) {\n      this.state.body = data;\n    } else if (typeof data === \"string\") {\n      this.state.body = Buffer.from(data, \"utf-8\");\n    } else {\n      this.state.body = Buffer.from(String(data), \"utf-8\");\n    }\n\n    this.serializeAndSend();\n  }\n\n  json(data: unknown): void {\n    this.checkFinished();\n\n    this.type(\"application/json\");\n    const jsonStr = JSON.stringify(data);\n    this.state.body = Buffer.from(jsonStr, \"utf-8\");\n    this.serializeAndSend();\n  }\n\n  text(data: string): void {\n    this.checkFinished();\n\n    this.type(\"text/plain\");\n    this.state.body = Buffer.from(data, \"utf-8\");\n    this.serializeAndSend();\n  }\n\n  html(data: string): void {\n    this.checkFinished();\n\n    this.type(\"text/html\");\n    this.state.body = Buffer.from(data, \"utf-8\");\n    this.serializeAndSend();\n  }\n\n  redirect(url: string, code?: number): void {\n    this.checkFinished();\n\n    this.state.status = code || 302;\n    this.header(\"location\", url);\n    this.serializeAndSend();\n  }\n\n  location(url: string): KitoResponse {\n    this.checkFinished();\n\n    return this.header(\"location\", url);\n  }\n\n  attachment(filename?: string): KitoResponse {\n    this.checkFinished();\n\n    if (filename) {\n      const encodedFilename = encodeURIComponent(filename);\n      return this.header(\n        \"content-disposition\",\n        `attachment; filename=\"${encodedFilename}\"`,\n      );\n    }\n\n    return this.header(\"content-disposition\", \"attachment\");\n  }\n\n  download(path: string, filename?: string, options?: SendFileOptions): void {\n    const name = filename || path.split(\"/\").pop() || \"download\";\n\n    this.attachment(name);\n    this.sendFile(path, options);\n  }\n\n  sendFile(path: string, options: SendFileOptions = {}): void {\n    this.checkFinished();\n\n    try {\n      const fullPath = options.root ? `${options.root}/${path}` : path;\n      const stats = statSync(fullPath);\n\n      this.state.body = readFileSync(fullPath);\n\n      const mimeType = this.getMimeType(path);\n      this.type(mimeType);\n\n      if (options.headers) {\n        this.headers(options.headers);\n      }\n\n      if (options.acceptRanges) {\n        this.header(\"accept-ranges\", \"bytes\");\n      }\n\n      if (options.cacheControl !== false) {\n        const maxAge = options.maxAge || 0;\n        let cacheControl = `public, max-age=${Math.floor(maxAge / 1000)}`;\n\n        if (options.immutable) {\n          cacheControl += \", immutable\";\n        }\n\n        this.header(\"cache-control\", cacheControl);\n      }\n\n      if (options.lastModified !== false) {\n        this.header(\"last-modified\", stats.mtime.toUTCString());\n      }\n\n      if (options.etag !== false) {\n        const etag = `W/\"${stats.size.toString(16)}-${stats.mtime.getTime().toString(16)}\"`;\n        this.header(\"etag\", etag);\n      }\n\n      this.serializeAndSend();\n    } catch (_) {\n      this.state.status = 404;\n      this.state.body = Buffer.from(\"File Not Found\", \"utf-8\");\n      this.serializeAndSend();\n    }\n  }\n\n  private getMimeType(path: string): string {\n    const extension = path.split(\".\").pop()?.toLowerCase() || \"\";\n\n    const mimeTypes: Record<string, string> = {\n      html: \"text/html\",\n      htm: \"text/html\",\n      css: \"text/css\",\n      js: \"application/javascript\",\n      mjs: \"application/javascript\",\n      json: \"application/json\",\n      xml: \"application/xml\",\n      txt: \"text/plain\",\n      png: \"image/png\",\n      jpg: \"image/jpeg\",\n      jpeg: \"image/jpeg\",\n      gif: \"image/gif\",\n      svg: \"image/svg+xml\",\n      webp: \"image/webp\",\n      ico: \"image/x-icon\",\n      pdf: \"application/pdf\",\n      zip: \"application/zip\",\n      wasm: \"application/wasm\",\n      mp4: \"video/mp4\",\n      webm: \"video/webm\",\n      mp3: \"audio/mpeg\",\n      wav: \"audio/wav\",\n      woff: \"font/woff2\",\n      woff2: \"font/woff2\",\n      ttf: \"font/ttf\",\n      otf: \"font/otf\",\n    };\n\n    return mimeTypes[extension] || \"application/octet-stream\";\n  }\n\n  vary(field: string): KitoResponse {\n    this.checkFinished();\n\n    return this.append(\"vary\", field);\n  }\n\n  links(links: Record<string, string>): KitoResponse {\n    this.checkFinished();\n\n    const linkHeader = Object.entries(links)\n      .map(([rel, url]) => `<${url}>; rel=\"${rel}\"`)\n      .join(\", \");\n\n    return this.header(\"link\", linkHeader);\n  }\n\n  format(obj: Record<string, () => void>): KitoResponse {\n    this.checkFinished();\n\n    const acceptHeader = this.get(\"accept\") || \"*/*\";\n\n    for (const [type, handler] of Object.entries(obj)) {\n      if (acceptHeader.includes(type) || acceptHeader.includes(\"*/*\")) {\n        handler();\n        return this;\n      }\n    }\n\n    const firstHandler = Object.values(obj)[0];\n    if (firstHandler) {\n      firstHandler();\n    }\n\n    return this;\n  }\n\n  stream(): StreamWriter {\n    this.checkFinished();\n\n    if (!this.state.headers.has(\"content-type\")) {\n      this.type(\"application/octet-stream\");\n    }\n\n    this.startStreamingResponse();\n\n    return new StreamWriterImpl(this.channel);\n  }\n\n  sse(): SSEWriter {\n    this.checkFinished();\n\n    this.type(\"text/event-stream\");\n    this.header(\"cache-control\", \"no-cache\");\n    this.header(\"connection\", \"keep-alive\");\n\n    this.startStreamingResponse();\n\n    return new SSEWriterImpl(this.channel);\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/src/server/router.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  HttpMethod,\n  MiddlewareDefinition,\n  SchemaDefinition,\n  RouteHandler,\n  MiddlewareHandler,\n  RouteChain,\n  KitoRouterInstance,\n  RouteDefinition,\n} from \"@kitojs/types\";\n\n/**\n * Router class for Kito.\n * Provides HTTP routing and middleware support with the ability to mount sub-routers.\n *\n * @template TExtensions - Type of custom extensions added to the context\n *\n * @example\n * ```typescript\n * const router = new KitoRouter();\n *\n * router.get('/', ({ res }) => {\n *   res.send('Hello from router!');\n * });\n *\n * export default router;\n * ```\n */\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport class KitoRouter<TExtensions = {}>\n  implements KitoRouterInstance<TExtensions>\n{\n  protected routes: RouteDefinition<TExtensions>[] = [];\n  protected middlewares: MiddlewareDefinition[] = [];\n  protected prefix = \"\";\n\n  /**\n   * Registers a global middleware that runs for all routes in this router.\n   *\n   * @param middleware - Middleware function or definition\n   * @returns The router instance for chaining\n   *\n   * @example\n   * ```typescript\n   * router.use((ctx, next) => {\n   *   console.log(`${ctx.req.method} ${ctx.req.url}`);\n   *   next();\n   * });\n   * ```\n   */\n  use(middleware: MiddlewareDefinition | MiddlewareHandler): this {\n    if (typeof middleware === \"function\") {\n      this.middlewares.push({\n        type: \"function\",\n        handler: middleware,\n        global: true,\n      });\n    } else {\n      this.middlewares.push({ ...middleware, global: true });\n    }\n\n    return this;\n  }\n\n  /**\n   * Mounts a sub-router at the specified path.\n   *\n   * @param path - Base path for the sub-router\n   * @param router - Router instance to mount\n   * @returns The router instance for chaining\n   *\n   * @example\n   * ```typescript\n   * const apiRouter = router();\n   * apiRouter.get('/users', ({ res }) => res.json({ users: [] }));\n   *\n   * const app = server();\n   * app.mount('/api', apiRouter);\n   * ```\n   */\n  mount(path: string, router: KitoRouter<TExtensions>): this {\n    const normalizedPath = this.normalizePath(path);\n    const prefix = normalizedPath === \"/\" ? \"\" : normalizedPath;\n    const subRouterMiddlewares = router.getMiddlewares();\n\n    const mountedRoutes = router.getRoutes().map((route) => ({\n      ...route,\n      path: prefix + route.path,\n      middlewares: [...subRouterMiddlewares, ...route.middlewares],\n    }));\n\n    this.routes.push(...mountedRoutes);\n\n    return this;\n  }\n\n  /**\n   * Registers a GET route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"GET\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers a POST route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"POST\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers a PUT route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"PUT\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers a DELETE route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"DELETE\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers a PATCH route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"PATCH\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers a HEAD route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"HEAD\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Registers an OPTIONS route.\n   */\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): this;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): this {\n    this.addRoute<TSchema>(\n      \"OPTIONS\",\n      path,\n      middlewaresOrHandler,\n      handlerOrSchema,\n      schema,\n    );\n    return this;\n  }\n\n  /**\n   * Creates a route builder for chaining multiple HTTP methods on the same path.\n   *\n   * @param path - Base path for all routes in the chain\n   * @param routeMiddlewares - Optional middleware to apply to all routes in the chain\n   * @returns Route chain builder\n   *\n   * @example\n   * ```typescript\n   * router.route('/api/users')\n   *   .get(({ res }) => res.json(users))\n   *   .post(({ res }) => res.json({ created: true }))\n   *   .end();\n   * ```\n   *\n   * @example With middleware\n   * ```typescript\n   * const auth = middleware((ctx, next) => {\n   *   // authentication logic\n   *   next();\n   * });\n   *\n   * router.route('/admin', [auth])\n   *   .get(({ res }) => res.send('Admin dashboard'))\n   *   .post(({ res }) => res.send('Admin create'));\n   * ```\n   */\n  route(\n    path: string,\n    routeMiddlewares?: MiddlewareDefinition[] | MiddlewareDefinition,\n  ): RouteChain<TExtensions> {\n    const self = this;\n\n    const mergeMiddlewares = <TSchema extends SchemaDefinition>(\n      callMiddlewares?:\n        | (MiddlewareDefinition | TSchema)[]\n        | (MiddlewareDefinition | TSchema),\n    ): (MiddlewareDefinition | TSchema)[] => {\n      const normalizedRouteMiddlewares = Array.isArray(routeMiddlewares)\n        ? routeMiddlewares\n        : routeMiddlewares\n          ? [routeMiddlewares]\n          : [];\n\n      const normalizedCallMiddlewares = Array.isArray(callMiddlewares)\n        ? callMiddlewares\n        : callMiddlewares\n          ? [callMiddlewares]\n          : [];\n\n      return [...normalizedRouteMiddlewares, ...normalizedCallMiddlewares] as (\n        | MiddlewareDefinition\n        | TSchema\n      )[];\n    };\n\n    const chain: RouteChain<TExtensions> = {\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      get<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"GET\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"GET\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      post<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"POST\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"POST\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      put<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"PUT\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"PUT\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      delete<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"DELETE\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"DELETE\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      patch<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"PATCH\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"PATCH\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      options<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"OPTIONS\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"OPTIONS\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      // biome-ignore lint/complexity/noBannedTypes: ...\n      head<TSchema extends SchemaDefinition = {}>(\n        middlewaresOrHandler:\n          | (MiddlewareDefinition | TSchema)[]\n          | (MiddlewareDefinition | TSchema)\n          | RouteHandler<TSchema, TExtensions>,\n        handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n      ): RouteChain<TExtensions> {\n        if (typeof middlewaresOrHandler === \"function\") {\n          self.addRoute(\n            \"HEAD\",\n            path,\n            mergeMiddlewares<TSchema>(),\n            middlewaresOrHandler,\n            handlerOrSchema as TSchema,\n          );\n        } else {\n          self.addRoute(\n            \"HEAD\",\n            path,\n            mergeMiddlewares<TSchema>(middlewaresOrHandler),\n            handlerOrSchema as RouteHandler<TSchema, TExtensions>,\n          );\n        }\n        return chain;\n      },\n\n      end(): KitoRouter<TExtensions> {\n        return self;\n      },\n    };\n\n    return chain;\n  }\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  protected addRoute<TSchema extends SchemaDefinition = {}>(\n    method: HttpMethod,\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n    schema?: TSchema,\n  ): void {\n    let finalHandler: RouteHandler<TSchema, TExtensions>;\n    let middlewares: (MiddlewareDefinition | TSchema)[] = [];\n\n    if (typeof middlewaresOrHandler === \"function\") {\n      finalHandler = middlewaresOrHandler as RouteHandler<TSchema, TExtensions>;\n\n      if (handlerOrSchema && this.isSchemaDefinition(handlerOrSchema)) {\n        middlewares = [handlerOrSchema as TSchema];\n      }\n    } else {\n      if (Array.isArray(middlewaresOrHandler)) {\n        middlewares = middlewaresOrHandler as (\n          | MiddlewareDefinition\n          | TSchema\n        )[];\n      } else {\n        middlewares = [middlewaresOrHandler as MiddlewareDefinition | TSchema];\n      }\n      finalHandler = handlerOrSchema as RouteHandler<TSchema, TExtensions>;\n    }\n\n    if (schema) {\n      middlewares.push(schema);\n    }\n\n    const normalizedPath = this.normalizePath(path);\n\n    this.routes.push({\n      method,\n      path: normalizedPath,\n      middlewares,\n      handler: finalHandler as RouteHandler<SchemaDefinition, TExtensions>,\n    });\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  protected isSchemaDefinition(item: any): item is SchemaDefinition {\n    return item && (item.params || item.query || item.body || item.headers);\n  }\n\n  protected getRoutes(): RouteDefinition<TExtensions>[] {\n    return this.routes;\n  }\n\n  protected getMiddlewares(): MiddlewareDefinition[] {\n    return this.middlewares;\n  }\n\n  private normalizePath(path: string): string {\n    let normalized = path.startsWith(\"/\") ? path : `/${path}`;\n    if (normalized.length > 1 && normalized.endsWith(\"/\")) {\n      normalized = normalized.slice(0, -1);\n    }\n\n    return normalized;\n  }\n}\n\n/**\n * Creates a new Router instance.\n *\n * @returns New router instance\n *\n * @example\n * ```typescript\n * import { router } from 'kitojs';\n *\n * const cats = router();\n *\n * cats.get('/', ({ res }) => {\n *   res.send('hello from cats!');\n * });\n *\n * export default cats;\n * ```\n */\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport function router<TExtensions = {}>(): KitoRouter<TExtensions> {\n  return new KitoRouter<TExtensions>();\n}\n"
  },
  {
    "path": "packages/kitojs/src/server/server.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type {\n  HttpMethod,\n  MiddlewareDefinition,\n  SchemaDefinition,\n  ServerOptions,\n  RouteHandler,\n  KitoContext,\n  KitoServerInstance,\n} from \"@kitojs/types\";\n\nimport { ServerCore, type ServerOptionsCore } from \"@kitojs/kito-core\";\nimport { RequestBuilder } from \"./request\";\nimport { ResponseBuilder } from \"./response\";\n\nimport { analyzeHandler, type StaticResponseType } from \"./analyzer\";\nimport { KitoRouter } from \"./router\";\n\n/**\n * Main server class for Kito framework.\n * Extends Router to provide HTTP routing, middleware support, and adds server-specific functionality.\n *\n * @template TExtensions - Type of custom extensions added to the context\n *\n * @example\n * ```typescript\n * const app = new KitoServer();\n *\n * app.get('/', ctx => {\n *   ctx.res.send('Hello World!');\n * });\n *\n * app.listen(3000);\n * ```\n */\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport class KitoServer<TExtensions = {}>\n  extends KitoRouter<TExtensions>\n  implements KitoServerInstance<TExtensions>\n{\n  private serverOptions: ServerOptions = {};\n\n  private coreServer: ServerCore;\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  private extensionFn?: (ctx: any) => void;\n\n  /**\n   * Creates a new Kito server instance.\n   *\n   * @param options - Server configuration options\n   * @param options.port - Port to listen on (default: 3000)\n   * @param options.host - Host to bind to (default: \"0.0.0.0\")\n   * @param options.trustProxy - Trust X-Forwarded-* headers\n   * @param options.maxRequestSize - Maximum request body size in bytes\n   * @param options.timeout - Request timeout in milliseconds\n   */\n  constructor(options?: ServerOptions) {\n    super();\n    this.serverOptions = { ...this.serverOptions, ...options };\n    this.coreServer = new ServerCore({\n      port: options?.unixSocket ? undefined : options?.port,\n      host: options?.unixSocket ? undefined : options?.host,\n      unixSocket: options?.unixSocket,\n      reusePort: options?.reusePort,\n      trustProxy: options?.trustProxy,\n      maxRequestSize: options?.maxRequestSize,\n      timeout: options?.timeout,\n    });\n  }\n\n  /**\n   * Extends the request context with custom properties or methods.\n   *\n   * @template TNewExtensions - Type of the new extensions\n   * @param fn - Function that adds extensions to the context\n   * @returns A new server instance with extended context type\n   *\n   * @example\n   * ```typescript\n   * interface Database {\n   *   query: (sql: string) => Promise<any>;\n   * }\n   *\n   * const app = server().extend<{ db: Database }>(ctx => {\n   *   ctx.db = createDatabase();\n   * });\n   *\n   * app.get('/users', ctx => {\n   *   const users = await ctx.db.query('SELECT * FROM users');\n   *   ctx.res.json(users);\n   * });\n   * ```\n   */\n  extend<TNewExtensions = unknown>(\n    fn: (\n      ctx: KitoContext & TExtensions & Partial<TNewExtensions>,\n      // biome-ignore lint/suspicious/noConfusingVoidType: ...\n    ) => TNewExtensions | void,\n  ): KitoServer<TExtensions & TNewExtensions> {\n    const newServer = new KitoServer<TExtensions & TNewExtensions>(\n      this.serverOptions,\n    );\n\n    newServer.middlewares = [...this.middlewares];\n    newServer.routes = [...this.routes];\n\n    newServer.coreServer = this.coreServer;\n\n    const previousExtensionFn = this.extensionFn;\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    newServer.extensionFn = (ctx: any) => {\n      if (previousExtensionFn) {\n        previousExtensionFn(ctx);\n      }\n\n      const result = fn(ctx);\n      if (result && typeof result === \"object\") {\n        Object.assign(ctx, result);\n      }\n    };\n\n    return newServer;\n  }\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  protected override addRoute<TSchema extends SchemaDefinition = {}>(\n    method: HttpMethod,\n    path: string,\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | RouteHandler<TSchema, TExtensions>,\n    handler?: RouteHandler<TSchema, TExtensions>,\n    schema?: TSchema,\n  ): void {\n    super.addRoute(method, path, middlewaresOrHandler, handler, schema);\n\n    const route = this.routes[this.routes.length - 1];\n\n    this.registerRouteWithCore(route);\n  }\n\n  override mount(path: string, router: KitoRouter<TExtensions>): this {\n    const routeIndex = this.routes.length;\n    super.mount(path, router);\n\n    for (let i = routeIndex; i < this.routes.length; i++) {\n      this.registerRouteWithCore(this.routes[i]);\n    }\n\n    return this;\n  }\n\n  private registerRouteWithCore(\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    route: any,\n  ): void {\n    let finalHandler: RouteHandler<SchemaDefinition, TExtensions>;\n    let middlewares: (MiddlewareDefinition | SchemaDefinition)[] = [];\n\n    finalHandler = route.handler;\n    middlewares = route.middlewares || [];\n\n    const routeMiddlewares: MiddlewareDefinition[] = [];\n    let routeSchema: SchemaDefinition | undefined;\n\n    for (const item of middlewares) {\n      if (this.isSchemaDefinition(item)) {\n        routeSchema = item as SchemaDefinition;\n        routeMiddlewares.push({\n          type: \"schema\",\n          // biome-ignore lint/suspicious/noExplicitAny: ...\n          schema: item as any,\n          global: false,\n        });\n      } else {\n        routeMiddlewares.push({\n          ...(item as MiddlewareDefinition),\n          global: false,\n        });\n      }\n    }\n\n    let staticResponse: StaticResponseType = { type: \"none\" };\n\n    if (this.middlewares.length === 0 && routeMiddlewares.length === 0) {\n      staticResponse = analyzeHandler(finalHandler);\n    }\n\n    const fusedHandler = this.fuseMiddlewares(\n      this.middlewares,\n      routeMiddlewares,\n      finalHandler,\n    );\n\n    const routeHandler = async (ctx: KitoContext<SchemaDefinition>) => {\n      const reqBuilder = new RequestBuilder(ctx.req);\n      const resBuilder = new ResponseBuilder(ctx.res);\n\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      const context: any = { req: reqBuilder, res: resBuilder };\n\n      if (this.extensionFn) {\n        this.extensionFn(context);\n      }\n\n      await fusedHandler(context);\n    };\n\n    const schemaJson = routeSchema\n      ? this.serializeSchema(routeSchema)\n      : undefined;\n\n    const staticResponseJson =\n      staticResponse.type !== \"none\"\n        ? JSON.stringify(staticResponse)\n        : undefined;\n\n    this.coreServer.addRoute({\n      method: route.method,\n      path: route.path,\n      handler: routeHandler,\n      schema: schemaJson,\n      staticResponse: staticResponseJson,\n    });\n  }\n\n  private serializeSchema(schema: SchemaDefinition): string {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    const serialized: any = {};\n\n    if (schema.params) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      serialized.params = (schema.params as any)._serialize();\n    }\n    if (schema.query) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      serialized.query = (schema.query as any)._serialize();\n    }\n    if (schema.body) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      serialized.body = (schema.body as any)._serialize();\n    }\n    if (schema.headers) {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      serialized.headers = (schema.headers as any)._serialize();\n    }\n\n    return JSON.stringify(serialized);\n  }\n\n  private registerCatchAllRoute(): void {\n    const hasCatchAll = this.routes.some(\n      (route) =>\n        route.path === \"{*path}\" || route.path === \"/*\" || route.path === \"*\",\n    );\n\n    if (hasCatchAll) return;\n\n    const catchAllHandler: RouteHandler<SchemaDefinition, TExtensions> = (\n      ctx,\n    ) => {\n      try {\n        ctx.res.status(404).send(\"Not Found\");\n      } catch {}\n    };\n\n    const fusedHandler = this.fuseMiddlewares(\n      this.middlewares,\n      [],\n      catchAllHandler,\n    );\n\n    const routeHandler = async (ctx: KitoContext<SchemaDefinition>) => {\n      const reqBuilder = new RequestBuilder(ctx.req);\n      const resBuilder = new ResponseBuilder(ctx.res);\n\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      const context: any = { req: reqBuilder, res: resBuilder };\n\n      if (this.extensionFn) {\n        this.extensionFn(context);\n      }\n\n      await fusedHandler(context);\n    };\n\n    const methods: HttpMethod[] = [\n      \"GET\",\n      \"POST\",\n      \"PUT\",\n      \"DELETE\",\n      \"PATCH\",\n      \"HEAD\",\n      \"OPTIONS\",\n    ];\n\n    for (const method of methods) {\n      try {\n        this.coreServer.addRoute({\n          method,\n          path: \"/{*path}\",\n          handler: routeHandler,\n          schema: undefined,\n          staticResponse: undefined,\n        });\n      } catch (e) {\n        // Suppress conflict error\n      }\n    }\n  }\n\n  private fuseMiddlewares<TSchema extends SchemaDefinition>(\n    globals: MiddlewareDefinition[],\n    routeMiddlewares: MiddlewareDefinition[],\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteHandler<TSchema, TExtensions> {\n    const functions = [\n      ...globals\n        .filter((m) => m.type === \"function\" && m.handler)\n        // biome-ignore lint/style/noNonNullAssertion: ...\n        .map((m) => m.handler!),\n      ...routeMiddlewares\n        .filter((m) => m.type === \"function\" && m.handler)\n        // biome-ignore lint/style/noNonNullAssertion: ...\n        .map((m) => m.handler!),\n    ];\n\n    if (functions.length === 0)\n      return handler as RouteHandler<TSchema, TExtensions>;\n\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    return async (ctx: any) => {\n      let i = 0;\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      const next = async (): Promise<any> => {\n        if (i < functions.length) {\n          const fn = functions[i++];\n          return fn(ctx, next);\n        } else {\n          return handler(ctx);\n        }\n      };\n      return next();\n    };\n  }\n\n  /**\n   * Starts the server.\n   *\n   * You can call `listen` in multiple ways:\n   *\n   * **1. Using a port (classic usage)**\n   * ```ts\n   * app.listen(3000);\n   * app.listen(3000, \"0.0.0.0\");\n   * app.listen(3000, () => console.log(\"Ready\"));\n   * app.listen(3000, \"0.0.0.0\", () => console.log(\"Ready\"));\n   * ```\n   *\n   * **2. Using an options object**\n   * ```ts\n   * app.listen({\n   *   port: 3000,\n   *   host: \"0.0.0.0\",\n   * });\n   * ```\n   *\n   * **3. Listening on a Unix Domain Socket**\n   * ```ts\n   * app.listen({\n   *   unixSocket: \"/tmp/kito.sock\",\n   * });\n   * ```\n   *\n   * When `unixSocket` is provided:\n   * - `port` and `host` are ignored\n   * - The server binds exclusively to the provided socket path\n   *\n   * You may also pass a callback as the last argument in all forms.\n   *\n   * @param portOrCallbackOrOptions Port number, callback, or a full `ServerOptions` object.\n   * @param hostOrCallback Hostname or callback.\n   * @param maybeCallback Optional callback executed once the server starts.\n   * @returns The resolved server configuration.\n   */\n  async listen(\n    portOrCallbackOrOptions?: number | (() => void) | ServerOptions,\n    hostOrCallback?: string | (() => void),\n    maybeCallback?: () => void,\n  ): Promise<ServerOptionsCore> {\n    let port: number | undefined;\n    let host: string | undefined;\n    let unixSocket: string | undefined;\n    let reusePort: boolean | undefined;\n    let ready: (() => void) | undefined;\n\n    if (typeof portOrCallbackOrOptions === \"object\") {\n      const options = portOrCallbackOrOptions;\n      port = options.port;\n      host = options.host;\n      unixSocket = options.unixSocket;\n      reusePort = options.reusePort;\n      ready = hostOrCallback as (() => void) | undefined;\n    } else if (typeof portOrCallbackOrOptions === \"function\") {\n      ready = portOrCallbackOrOptions;\n    } else {\n      port = portOrCallbackOrOptions;\n      if (typeof hostOrCallback === \"function\") {\n        ready = hostOrCallback;\n      } else {\n        host = hostOrCallback;\n        ready = maybeCallback;\n      }\n    }\n\n    const finalUnixSocket = unixSocket ?? this.serverOptions.unixSocket;\n    const finalReusePort = reusePort ?? this.serverOptions.reusePort ?? false;\n    const finalPort = finalUnixSocket\n      ? undefined\n      : (port ?? this.serverOptions.port ?? 3000);\n    const finalHost = finalUnixSocket\n      ? undefined\n      : (host ?? this.serverOptions.host ?? \"0.0.0.0\");\n\n    if (this.middlewares.length > 0) {\n      this.registerCatchAllRoute();\n    }\n\n    const configuration: ServerOptionsCore = {\n      port: finalPort,\n      host: finalHost,\n      unixSocket: finalUnixSocket,\n      reusePort: finalReusePort,\n      trustProxy: this.serverOptions.trustProxy,\n      maxRequestSize: this.serverOptions.maxRequestSize,\n      timeout: this.serverOptions.timeout,\n    };\n\n    this.coreServer.setConfig(configuration);\n    await this.coreServer.start(ready);\n\n    return configuration;\n  }\n\n  /**\n   * Closes the server and stops accepting new connections.\n   */\n  close(): void {\n    this.coreServer.close();\n  }\n}\n\n/**\n * Creates a new Kito server instance.\n *\n * @param options - Server configuration options\n * @returns New server instance\n *\n * @example\n * ```typescript\n * import { server } from 'kitojs';\n *\n * const app = server();\n *\n * app.get('/', ctx => {\n *   ctx.res.send('Hello World!');\n * });\n *\n * app.listen(3000);\n * ```\n */\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport function server(options?: ServerOptions): KitoServer<{}> {\n  return new KitoServer(options);\n}\n"
  },
  {
    "path": "packages/kitojs/src/types.ts",
    "content": "export type { Context, KitoContext } from \"@kitojs/types\";\n\nexport type {\n  CommonHeaderNames,\n  RequestHeaders,\n  ParsedUrl,\n  KitoRequest,\n} from \"@kitojs/types\";\n\nexport type {\n  CommonResponseHeaderNames,\n  SendFileOptions,\n  CookieOptions,\n  StreamWriter,\n  SSEWriter,\n  KitoResponse,\n} from \"@kitojs/types\";\n\nexport type {\n  NextFunction,\n  MiddlewareHandler,\n  RouteHandler,\n} from \"@kitojs/types\";\n\nexport type {\n  HttpMethod,\n  RouteDefinition,\n  MiddlewareDefinition,\n  RouteChain,\n  KitoRouterInstance,\n  ServerOptions,\n  KitoServerInstance,\n} from \"@kitojs/types\";\n"
  },
  {
    "path": "packages/kitojs/tests/analyzer.test.ts",
    "content": "import { describe, expect, it } from \"vitest\";\n\nimport { analyzeHandler } from \"../src/server/analyzer\";\nimport type { Context } from \"@kitojs/types\";\n\ndescribe(\"Static Response Analyzer\", () => {\n  it(\"should detect full static response\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.json({ message: \"hello\" });\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"full_static\");\n    if (result.type === \"full_static\") {\n      expect(result.status).toBe(200);\n      expect(result.method).toBe(\"json\");\n      expect(result.headers[\"content-type\"]).toBe(\"application/json\");\n    }\n  });\n\n  it(\"should detect static text response\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.text(\"hello world\");\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"full_static\");\n    if (result.type === \"full_static\") {\n      expect(result.method).toBe(\"text\");\n      expect(result.headers[\"content-type\"]).toBe(\"text/plain\");\n    }\n  });\n\n  it(\"should detect static HTML response\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.html(\"<h1>Hello</h1>\");\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"full_static\");\n    if (result.type === \"full_static\") {\n      expect(result.method).toBe(\"html\");\n      expect(result.headers[\"content-type\"]).toBe(\"text/html\");\n    }\n  });\n\n  it(\"should detect non-static response with logic\", () => {\n    const handler = (ctx: Context) => {\n      const data = Math.random();\n      ctx.res.json({ data });\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"none\");\n  });\n\n  it(\"should detect non-static response with if statement\", () => {\n    const handler = (ctx: Context) => {\n      if (ctx.req.query.admin) {\n        ctx.res.send(\"admin\");\n      } else {\n        ctx.res.send(\"user\");\n      }\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"none\");\n  });\n\n  it(\"should detect param template response\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.json({\n        id: ctx.req.params.id,\n        name: ctx.req.params.name,\n      });\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"param_template\");\n    if (result.type === \"param_template\") {\n      expect(result.params).toContain(\"id\");\n      expect(result.params).toContain(\"name\");\n      expect(result.template).toContain(\"{{params.id}}\");\n      expect(result.template).toContain(\"{{params.name}}\");\n    }\n  });\n\n  it(\"should detect none for complex handlers\", () => {\n    const handler = async (ctx: Context) => {\n      const user = await fetchUser(ctx.req.params.id);\n      ctx.res.json(user);\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"none\");\n  });\n\n  it(\"should detect none for multiple response calls\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.send(\"first\");\n      ctx.res.send(\"second\");\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"none\");\n  });\n\n  it(\"should handle arrow functions\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.send(\"arrow\");\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"full_static\");\n  });\n\n  it(\"should detect static object response\", () => {\n    const handler = (ctx: Context) => {\n      ctx.res.json({\n        status: \"ok\",\n        version: \"1.0.0\",\n        features: [\"fast\", \"secure\"],\n      });\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"full_static\");\n  });\n\n  it(\"should detect none for variable declarations\", () => {\n    const handler = (ctx: Context) => {\n      const message = \"hello\";\n      ctx.res.send(message);\n    };\n\n    const result = analyzeHandler(handler);\n    expect(result.type).toBe(\"none\");\n  });\n});\n\nfunction fetchUser(id: string) {\n  return Promise.resolve({ id, name: \"User\" });\n}\n"
  },
  {
    "path": "packages/kitojs/tests/middleware.test.ts",
    "content": "import { describe, expect, it } from \"vitest\";\nimport { middleware } from \"../src\";\n\ndescribe(\"Middleware Helper\", () => {\n  it(\"should create middleware definition\", () => {\n    const mw = middleware((_, next) => {\n      next();\n    });\n\n    expect(mw).toHaveProperty(\"type\", \"function\");\n    expect(mw).toHaveProperty(\"handler\");\n    expect(mw).toHaveProperty(\"global\", false);\n    expect(typeof mw.handler).toBe(\"function\");\n  });\n\n  it(\"should preserve handler function\", () => {\n    // biome-ignore lint/suspicious/noExplicitAny: ...\n    const handler = (ctx: any, next: any) => {\n      ctx.custom = \"value\";\n      next();\n    };\n\n    const mw = middleware(handler);\n    expect(mw.handler).toBe(handler);\n  });\n\n  it(\"should have correct structure\", () => {\n    const mw = middleware((_, next) => next());\n\n    expect(mw.type).toBe(\"function\");\n    expect(mw.global).toBe(false);\n    expect(mw.handler).toBeDefined();\n  });\n\n  it(\"should support async handlers\", () => {\n    const asyncMw = middleware(async (_, next) => {\n      await Promise.resolve();\n      next();\n    });\n\n    expect(asyncMw.handler).toBeDefined();\n    expect(asyncMw.handler?.constructor.name).toBe(\"AsyncFunction\");\n  });\n\n  it(\"should work with route() method\", async () => {\n    const { server } = await import(\"../src\");\n\n    const executionLog: string[] = [];\n\n    const authMiddleware = middleware((ctx, next) => {\n      executionLog.push(\"auth\");\n      next();\n    });\n\n    const app = server();\n\n    app\n      .route(\"/admin\", [authMiddleware])\n      .get(({ res }) => {\n        executionLog.push(\"get-handler\");\n        res.send(\"Admin GET\");\n      })\n      .post(({ res }) => {\n        executionLog.push(\"post-handler\");\n        res.send(\"Admin POST\");\n      });\n\n    const routes = app[\"routes\"];\n    expect(routes).toHaveLength(2);\n\n    expect(routes[0].middlewares).toHaveLength(1);\n    expect(routes[1].middlewares).toHaveLength(1);\n    expect(routes[0].middlewares[0]).toBe(authMiddleware);\n    expect(routes[1].middlewares[0]).toBe(authMiddleware);\n  });\n\n  it(\"should combine route and call-level middlewares\", async () => {\n    const { server, middleware } = await import(\"../src\");\n\n    const routeLevelMw = middleware((_, next) => next());\n    const callLevelMw = middleware((_, next) => next());\n\n    const app = server();\n\n    app.route(\"/admin\", [routeLevelMw]).get([callLevelMw], ({ res }) => {\n      res.send(\"Admin\");\n    });\n\n    const routes = app[\"routes\"];\n    expect(routes).toHaveLength(1);\n    expect(routes[0].middlewares).toHaveLength(2);\n    expect(routes[0].middlewares[0]).toBe(routeLevelMw);\n    expect(routes[0].middlewares[1]).toBe(callLevelMw);\n  });\n\n  it(\"should execute route middleware before handler\", async () => {\n    const { server, middleware } = await import(\"../src\");\n\n    const executionOrder: string[] = [];\n\n    const authMw = middleware((_, next) => {\n      executionOrder.push(\"route-middleware\");\n      next();\n    });\n\n    const app = server();\n\n    app.route(\"/protected\", [authMw]).get(({ res }) => {\n      executionOrder.push(\"handler\");\n      res.send(\"Protected\");\n    });\n\n    const routes = app[\"routes\"];\n    expect(routes[0].middlewares[0]).toBe(authMw);\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tests/route-chain.test.ts",
    "content": "import type { SchemaDefinition } from \"@kitojs/types\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { middleware, router, server } from \"../src\";\n\ndescribe(\"Route Chaining\", () => {\n  describe(\"Server Chaining\", () => {\n    it(\"should support fluent API (method chaining)\", () => {\n      const app = server();\n      expect(() => {\n        app\n          .get(\"/\", (ctx) => ctx.res.send(\"home\"))\n          .post(\"/users\", (ctx) => ctx.res.json({ created: true }))\n          .get(\"/about\", (ctx) => ctx.res.send(\"about\"));\n      }).not.toThrow();\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(routes).toHaveLength(3);\n    });\n\n    it(\"should use route() builder\", () => {\n      const app = server();\n      const routes = app.route(\"/api\");\n\n      expect(typeof routes.get).toBe(\"function\");\n      expect(typeof routes.post).toBe(\"function\");\n      expect(typeof routes.end).toBe(\"function\");\n    });\n\n    it(\"should chain routes and end\", () => {\n      const app = server();\n      expect(() => {\n        app\n          .route(\"/api\")\n          .get((ctx) => ctx.res.send(\"get\"))\n          .post((ctx) => ctx.res.send(\"post\"))\n          .end()\n          .get(\"/\", (ctx) => ctx.res.send(\"home\"));\n      }).not.toThrow();\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(routes).toHaveLength(3);\n    });\n\n    it(\"should work correctly with server().route() chaining and core registration\", async () => {\n      const app = server();\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const spy = vi.spyOn(app[\"coreServer\"], \"addRoute\");\n\n      app\n        .route(\"/direct\")\n        .get((ctx) => ctx.res.send(\"get\"))\n        .post((ctx) => ctx.res.send(\"post\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(\n        routes.find((r) => r.path === \"/direct\" && r.method === \"GET\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.path === \"/direct\" && r.method === \"POST\"),\n      ).toBeDefined();\n\n      // Verify it's actually registered in the core server via spy\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy).toHaveBeenCalledWith(\n        expect.objectContaining({ path: \"/direct\", method: \"GET\" }),\n      );\n      expect(spy).toHaveBeenCalledWith(\n        expect.objectContaining({ path: \"/direct\", method: \"POST\" }),\n      );\n    });\n\n    it(\"should correctly handle schema in server().route() chaining\", () => {\n      const app = server();\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const spy = vi.spyOn(app[\"coreServer\"], \"addRoute\");\n\n      // Use proper schema builder mock\n      const userSchema = {\n        params: {\n          _serialize: () => JSON.stringify({ id: \"string\" }),\n        },\n      };\n\n      app.route(\"/search\").get((ctx) => ctx.res.send(\"ok\"), userSchema as any);\n\n      expect(spy).toHaveBeenCalledWith(\n        expect.objectContaining({\n          path: \"/search\",\n          method: \"GET\",\n          schema: JSON.stringify({ params: JSON.stringify({ id: \"string\" }) }),\n        }),\n      );\n    });\n  });\n\n  describe(\"Router Chaining\", () => {\n    it(\"should handle route chaining\", () => {\n      const r = router();\n      r.route(\"/users\")\n        .get((ctx) => ctx.res.send(\"list\"))\n        .post((ctx) => ctx.res.send(\"create\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(\n        routes.find((r) => r.method === \"GET\" && r.path === \"/users\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"POST\" && r.path === \"/users\"),\n      ).toBeDefined();\n    });\n\n    it(\"should support all HTTP methods in a chain\", () => {\n      const r = router();\n      r.route(\"/multi\")\n        .get((ctx) => ctx.res.send(\"get\"))\n        .post((ctx) => ctx.res.send(\"post\"))\n        .put((ctx) => ctx.res.send(\"put\"))\n        .delete((ctx) => ctx.res.send(\"delete\"))\n        .patch((ctx) => ctx.res.send(\"patch\"))\n        .head((ctx) => ctx.res.send(\"head\"))\n        .options((ctx) => ctx.res.send(\"options\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(routes).toHaveLength(7);\n      const methods = routes.map((r) => r.method);\n      expect(methods).toContain(\"GET\");\n      expect(methods).toContain(\"POST\");\n      expect(methods).toContain(\"PUT\");\n      expect(methods).toContain(\"DELETE\");\n      expect(methods).toContain(\"PATCH\");\n      expect(methods).toContain(\"HEAD\");\n      expect(methods).toContain(\"OPTIONS\");\n    });\n\n    it(\"should apply route-level middlewares to all methods in the chain\", () => {\n      const mw = middleware((_ctx, next) => next());\n      const r = router();\n      r.route(\"/chain-mw\", [mw])\n        .get((ctx) => ctx.res.send(\"ok\"))\n        .post((ctx) => ctx.res.send(\"ok\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(routes[0].middlewares).toHaveLength(1);\n      expect(routes[1].middlewares).toHaveLength(1);\n      expect(routes[0].middlewares[0]).toBe(mw);\n      expect(routes[1].middlewares[0]).toBe(mw);\n    });\n\n    it(\"should correctly combine route-level and method-level middlewares\", () => {\n      const routeMw = middleware((_ctx, next) => next());\n      const methodMw = middleware((_ctx, next) => next());\n      const r = router();\n\n      r.route(\"/combined\", [routeMw]).get([methodMw], (ctx) =>\n        ctx.res.send(\"ok\"),\n      );\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(routes[0].middlewares).toHaveLength(2);\n      expect(routes[0].middlewares[0]).toBe(routeMw);\n      expect(routes[0].middlewares[1]).toBe(methodMw);\n    });\n\n    it(\"should support schema application for individual methods in a chain\", () => {\n      const schema = { params: { id: \"string\" } };\n      const r = router();\n\n      r.route(\"/schema\").get(\n        (ctx) => ctx.res.send(\"ok\"),\n        schema as unknown as SchemaDefinition,\n      );\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      // middlewares should contain the schema if provided\n      expect(routes[0].middlewares).toContain(schema);\n    });\n\n    it(\"should work correctly when the router is mounted on a server\", () => {\n      const sub = router();\n      sub\n        .route(\"/resource\")\n        .get((ctx) => ctx.res.send(\"get\"))\n        .post((ctx) => ctx.res.send(\"post\"));\n\n      const app = server();\n      app.mount(\"/api\", sub);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(\n        routes.find((r) => r.path === \"/api/resource\" && r.method === \"GET\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.path === \"/api/resource\" && r.method === \"POST\"),\n      ).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tests/router.test.ts",
    "content": "import type { Route } from \"@kitojs/kito-core\";\nimport type { MiddlewareDefinition } from \"@kitojs/types\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { middleware, router, server } from \"../src\";\n\ndescribe(\"Router\", () => {\n  describe(\"Basic Routing\", () => {\n    it(\"should register routes with different HTTP methods\", () => {\n      const r = router();\n      r.get(\"/get\", (ctx) => ctx.res.send(\"get\"));\n      r.post(\"/post\", (ctx) => ctx.res.send(\"post\"));\n      r.put(\"/put\", (ctx) => ctx.res.send(\"put\"));\n      r.delete(\"/delete\", (ctx) => ctx.res.send(\"delete\"));\n      r.patch(\"/patch\", (ctx) => ctx.res.send(\"patch\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(\n        routes.find((r) => r.method === \"GET\" && r.path === \"/get\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"POST\" && r.path === \"/post\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"PUT\" && r.path === \"/put\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"DELETE\" && r.path === \"/delete\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"PATCH\" && r.path === \"/patch\"),\n      ).toBeDefined();\n    });\n\n    it(\"should handle route chaining\", () => {\n      const r = router();\n      r.route(\"/users\")\n        .get((ctx) => ctx.res.send(\"list\"))\n        .post((ctx) => ctx.res.send(\"create\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      expect(\n        routes.find((r) => r.method === \"GET\" && r.path === \"/users\"),\n      ).toBeDefined();\n      expect(\n        routes.find((r) => r.method === \"POST\" && r.path === \"/users\"),\n      ).toBeDefined();\n    });\n  });\n\n  describe(\"Middleware\", () => {\n    it(\"should work with NO middleware\", async () => {\n      const api = router();\n      api.get(\"/ping\", ({ res }) => res.send(\"pong\"));\n\n      const app = server();\n      app.mount(\"/api\", api);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      const route = routes.find((r) => r.path === \"/api/ping\");\n\n      expect(route).toBeDefined();\n      expect(route?.middlewares).toHaveLength(0);\n    });\n\n    it(\"should register local middlewares for a route\", () => {\n      const mw = middleware((_ctx, next) => next());\n      const r = router();\n      r.get(\"/test\", [mw], (ctx) => ctx.res.send(\"ok\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = r[\"routes\"];\n      const route = routes.find((r) => r.path === \"/test\");\n      expect(route?.middlewares).toHaveLength(1);\n      expect((route?.middlewares[0] as MiddlewareDefinition).handler).toBe(\n        mw.handler,\n      );\n    });\n\n    it(\"should register global middlewares for all routes\", () => {\n      const mw = middleware((_ctx, next) => next());\n      const r = router();\n      r.use(mw);\n      r.get(\"/test\", (ctx) => ctx.res.send(\"ok\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      expect(r[\"getMiddlewares\"]()).toHaveLength(1);\n    });\n\n    it(\"should handle middleware that throws an error\", async () => {\n      const app = server();\n      const mw = middleware(() => {\n        throw new Error(\"Middleware Error\");\n      });\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const addRouteSpy = vi.spyOn(app[\"coreServer\"], \"addRoute\");\n\n      app.get(\"/error\", [mw], (ctx) => ctx.res.send(\"ok\"));\n\n      const call = addRouteSpy.mock.calls.find(\n        (c) => (c[0] as Route).path === \"/error\",\n      );\n      if (!call) throw new Error(\"Route not registered\");\n      const handler = (call[0] as Route).handler;\n\n      const mockCtx = {\n        req: {\n          method: \"GET\",\n          url: \"/error\",\n          headers: {},\n          params: {},\n          query: {},\n          body: {},\n        },\n        res: {\n          status: vi.fn().mockReturnThis(),\n          send: vi.fn().mockReturnThis(),\n          json: vi.fn().mockReturnThis(),\n          header: vi.fn().mockReturnThis(),\n          cookie: vi.fn().mockReturnThis(),\n        },\n      };\n\n      await expect(handler(mockCtx)).rejects.toThrow(\"Middleware Error\");\n    });\n  });\n\n  describe(\"Router Mounting\", () => {\n    describe(\"Middleware Inheritance\", () => {\n      it(\"should correctly propagate sub-router middleware\", async () => {\n        const mw = middleware((_ctx, next) => next());\n        const api = router();\n        api.use(mw);\n        api.get(\"/test\", ({ res }) => res.send(\"ok\"));\n\n        const app = server();\n        app.mount(\"/api\", api);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const route = routes.find((r) => r.path === \"/api/test\");\n\n        expect(route).toBeDefined();\n        expect(route?.middlewares).toHaveLength(1);\n\n        const firstMw = route?.middlewares[0] as MiddlewareDefinition;\n        if (firstMw) {\n          expect(firstMw.handler).toBe(mw.handler);\n          expect(firstMw.global).toBe(true);\n        } else {\n          throw new Error(\"Middleware should be defined\");\n        }\n      });\n\n      it(\"should preserve order: sub-router middleware then route middleware\", async () => {\n        const mwGlobal = middleware((_ctx, next) => next());\n        const mwRoute = middleware((_ctx, next) => next());\n\n        const api = router();\n        api.use(mwGlobal);\n        api.get(\"/test\", [mwRoute], ({ res }) => res.send(\"ok\"));\n\n        const app = server();\n        app.mount(\"/api\", api);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const route = routes.find((r) => r.path === \"/api/test\");\n\n        expect(route?.middlewares).toHaveLength(2);\n\n        const firstMw = route?.middlewares[0] as MiddlewareDefinition;\n        const secondMw = route?.middlewares[1] as MiddlewareDefinition;\n\n        if (firstMw && secondMw) {\n          expect(firstMw.handler).toBe(mwGlobal.handler);\n          expect(secondMw.handler).toBe(mwRoute.handler);\n        } else {\n          throw new Error(\"Middlewares should be defined\");\n        }\n      });\n\n      it(\"should handle nested router mounting and maintain order\", async () => {\n        const mwA = middleware((_ctx, next) => next());\n        const mwB = middleware((_ctx, next) => next());\n        const mwC = middleware((_ctx, next) => next());\n\n        const routerC = router();\n        routerC.use(mwC);\n        routerC.get(\"/end\", ({ res }) => res.send(\"done\"));\n\n        const routerB = router();\n        routerB.use(mwB);\n        routerB.mount(\"/c\", routerC);\n\n        const routerA = router();\n        routerA.use(mwA);\n        routerA.mount(\"/b\", routerB);\n\n        const app = server();\n        app.mount(\"/sub\", routerA);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const route = routes.find((r) => r.path === \"/sub/b/c/end\");\n\n        expect(route).toBeDefined();\n        expect(route?.middlewares).toHaveLength(3);\n\n        if (route) {\n          const mws = route.middlewares as MiddlewareDefinition[];\n          expect(mws[0].handler).toBe(mwA.handler);\n          expect(mws[1].handler).toBe(mwB.handler);\n          expect(mws[2].handler).toBe(mwC.handler);\n        }\n      });\n\n      it(\"should handle deep nested mounting with correct middleware order\", async () => {\n        const m1 = middleware((_ctx, next) => next());\n        const m2 = middleware((_ctx, next) => next());\n        const m3 = middleware((_ctx, next) => next());\n\n        const r3 = router()\n          .use(m3)\n          .get(\"/p3\", ({ res }) => res.send(\"3\"));\n        const r2 = router().use(m2).mount(\"/r3\", r3);\n        const r1 = router().use(m1).mount(\"/r2\", r2);\n\n        const app = server();\n        app.mount(\"/r1\", r1);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const route = routes.find((r) => r.path === \"/r1/r2/r3/p3\");\n\n        expect(route).toBeDefined();\n        expect(route?.middlewares).toHaveLength(3);\n\n        if (route) {\n          const mws = route.middlewares as MiddlewareDefinition[];\n          expect(mws[0].handler).toBe(m1.handler);\n          expect(mws[1].handler).toBe(m2.handler);\n          expect(mws[2].handler).toBe(m3.handler);\n        }\n      });\n    });\n\n    describe(\"Isolation\", () => {\n      it(\"should ensure middleware isolation between sub-routers\", async () => {\n        const mw1 = middleware((_ctx, next) => next());\n        const mw2 = middleware((_ctx, next) => next());\n\n        const api1 = router();\n        api1.use(mw1);\n        api1.get(\"/r1\", ({ res }) => res.send(\"ok\"));\n\n        const api2 = router();\n        api2.use(mw2);\n        api2.get(\"/r2\", ({ res }) => res.send(\"ok\"));\n\n        const app = server();\n        app.mount(\"/api1\", api1);\n        app.mount(\"/api2\", api2);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const route1 = routes.find((r) => r.path === \"/api1/r1\");\n        const route2 = routes.find((r) => r.path === \"/api2/r2\");\n\n        expect(route1?.middlewares).toHaveLength(1);\n        expect(route2?.middlewares).toHaveLength(1);\n\n        const mw1Entry = route1?.middlewares[0] as MiddlewareDefinition;\n        const mw2Entry = route2?.middlewares[0] as MiddlewareDefinition;\n\n        if (mw1Entry) expect(mw1Entry.handler).toBe(mw1.handler);\n        if (mw2Entry) expect(mw2Entry.handler).toBe(mw2.handler);\n\n        // Ensure NO bleeding\n        expect(\n          route1?.middlewares.some(\n            (m) => (m as MiddlewareDefinition).handler === mw2.handler,\n          ),\n        ).toBe(false);\n        expect(\n          route2?.middlewares.some(\n            (m) => (m as MiddlewareDefinition).handler === mw1.handler,\n          ),\n        ).toBe(false);\n      });\n\n      it(\"should avoid middleware bleeding between siblings in deep nesting\", async () => {\n        const common = middleware((_ctx, next) => next());\n        const leftMw = middleware((_ctx, next) => next());\n        const rightMw = middleware((_ctx, next) => next());\n\n        const left = router()\n          .use(leftMw)\n          .get(\"/l\", ({ res }) => res.send(\"l\"));\n        const right = router()\n          .use(rightMw)\n          .get(\"/r\", ({ res }) => res.send(\"r\"));\n\n        const root = router()\n          .use(common)\n          .mount(\"/left\", left)\n          .mount(\"/right\", right);\n\n        const app = server();\n        app.mount(\"/api\", root);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const leftRoute = routes.find((r) => r.path === \"/api/left/l\");\n        const rightRoute = routes.find((r) => r.path === \"/api/right/r\");\n\n        expect(leftRoute?.middlewares).toHaveLength(2);\n        expect(rightRoute?.middlewares).toHaveLength(2);\n\n        const leftMws = (leftRoute?.middlewares ||\n          []) as MiddlewareDefinition[];\n        const rightMws = (rightRoute?.middlewares ||\n          []) as MiddlewareDefinition[];\n\n        expect(leftMws[0].handler).toBe(common.handler);\n        expect(leftMws[1].handler).toBe(leftMw.handler);\n        expect(rightMws[0].handler).toBe(common.handler);\n        expect(rightMws[1].handler).toBe(rightMw.handler);\n\n        expect(leftMws.some((m) => m.handler === rightMw.handler)).toBe(false);\n        expect(rightMws.some((m) => m.handler === leftMw.handler)).toBe(false);\n      });\n\n      it(\"should ensure middleware defined in router A is NOT applied in router B\", async () => {\n        const mwA = middleware((_ctx, next) => next());\n        const mwB = middleware((_ctx, next) => next());\n\n        const routerA = router()\n          .use(mwA)\n          .get(\"/a\", ({ res }) => res.send(\"a\"));\n        const routerB = router()\n          .use(mwB)\n          .get(\"/b\", ({ res }) => res.send(\"b\"));\n\n        const app = server();\n        app.mount(\"/group\", routerA);\n        app.mount(\"/group\", routerB);\n\n        // biome-ignore lint/complexity/useLiteralKeys: ...\n        const routes = app[\"routes\"];\n        const routeA = routes.find((r) => r.path === \"/group/a\");\n        const routeB = routes.find((r) => r.path === \"/group/b\");\n\n        expect(routeA?.middlewares).toHaveLength(1);\n        expect(routeB?.middlewares).toHaveLength(1);\n\n        expect(\n          routeA?.middlewares.some(\n            (m) => (m as MiddlewareDefinition).handler === mwB.handler,\n          ),\n        ).toBe(false);\n        expect(\n          routeB?.middlewares.some(\n            (m) => (m as MiddlewareDefinition).handler === mwA.handler,\n          ),\n        ).toBe(false);\n      });\n    });\n\n    it(\"should handle mixed route mounting: direct routes and sub-routers\", async () => {\n      const subMw = middleware((_ctx, next) => next());\n\n      const sub = router();\n      sub.use(subMw);\n      sub.get(\"/sub-route\", ({ res }) => res.send(\"ok\"));\n\n      const app = server();\n      app.get(\"/direct\", ({ res }) => res.send(\"ok\"));\n      app.mount(\"/mounted\", sub);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const appRoutes = app[\"routes\"];\n      const directRoute = appRoutes.find((r) => r.path === \"/direct\");\n      const mountedRoute = appRoutes.find(\n        (r) => r.path === \"/mounted/sub-route\",\n      );\n\n      expect(directRoute?.middlewares).toHaveLength(0);\n      expect(mountedRoute?.middlewares).toHaveLength(1);\n\n      const firstMw = mountedRoute?.middlewares[0] as MiddlewareDefinition;\n      if (firstMw) {\n        expect(firstMw.handler).toBe(subMw.handler);\n      }\n    });\n\n    it(\"should handle mounting at root path '/'\", () => {\n      const sub = router();\n      sub.get(\"/test\", (ctx) => ctx.res.send(\"ok\"));\n\n      const app = server();\n      app.mount(\"/\", sub);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(routes.find((r) => r.path === \"/test\")).toBeDefined();\n    });\n\n    it(\"should handle mounting with trailing slashes\", () => {\n      const sub = router();\n      sub.get(\"/test/\", (ctx) => ctx.res.send(\"ok\"));\n\n      const app = server();\n      app.mount(\"/api/\", sub);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(routes.find((r) => r.path === \"/api/test\")).toBeDefined();\n    });\n\n    it(\"should handle redundant slashes in mounting\", () => {\n      const sub = router();\n      sub.get(\"//test\", (ctx) => ctx.res.send(\"ok\"));\n\n      const app = server();\n      app.mount(\"//api//\", sub);\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const routes = app[\"routes\"];\n      expect(routes.find((r) => r.path.includes(\"test\"))).toBeDefined();\n    });\n\n    it(\"should handle mounting an empty router\", () => {\n      const sub = router();\n      const app = server();\n\n      expect(() => app.mount(\"/api\", sub)).not.toThrow();\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      expect(app[\"routes\"]).toHaveLength(0);\n    });\n  });\n\n  describe(\"Server Integration\", () => {\n    it(\"should correctly propagate and execute sub-router middlewares\", async () => {\n      const app = server();\n      const mwCalled = vi.fn();\n      const mw = middleware((_ctx, next) => {\n        mwCalled();\n        return next();\n      });\n\n      const sub = router();\n      sub.get(\"/test\", [mw], (ctx) => ctx.res.send(\"ok\"));\n\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const addRouteSpy = vi.spyOn(app[\"coreServer\"], \"addRoute\");\n\n      app.mount(\"/api\", sub);\n\n      expect(addRouteSpy).toHaveBeenCalled();\n\n      // Find the registered handler for the mounted route\n      const call = addRouteSpy.mock.calls.find(\n        (c) => (c[0] as Route).path === \"/api/test\",\n      );\n      expect(call).toBeDefined();\n\n      const registeredHandler = (call as [Route])[0].handler;\n\n      // Mock context to simulate server execution\n      const mockCtx = {\n        req: {\n          method: \"GET\",\n          url: \"/api/test\",\n          headers: {},\n          params: {},\n          query: {},\n          body: {},\n        },\n        res: {\n          status: vi.fn().mockReturnThis(),\n          send: vi.fn().mockReturnThis(),\n          json: vi.fn().mockReturnThis(),\n          header: vi.fn().mockReturnThis(),\n          cookie: vi.fn().mockReturnThis(),\n        },\n      };\n\n      try {\n        await registeredHandler(mockCtx);\n      } catch (_e) {\n        // Ignore potential channel/response builder errors in mock environment\n      }\n\n      // Verification: The middleware on the sub-router MUST have been called\n      expect(mwCalled).toHaveBeenCalled();\n    });\n\n    it(\"should register routes with correctly fused middlewares in core server\", async () => {\n      const mwCalled = vi.fn();\n      const mw = middleware((_ctx, next) => {\n        mwCalled();\n        return next();\n      });\n\n      const sub = router();\n      sub.use(mw);\n      sub.get(\"/test\", (ctx) => ctx.res.send(\"ok\"));\n\n      const app = server();\n      // biome-ignore lint/complexity/useLiteralKeys: ...\n      const addRouteSpy = vi.spyOn(app[\"coreServer\"], \"addRoute\");\n\n      app.mount(\"/api\", sub);\n\n      expect(addRouteSpy).toHaveBeenCalled();\n\n      const call = addRouteSpy.mock.calls.find(\n        (c) => (c[0] as Route).path === \"/api/test\",\n      );\n      expect(call).toBeDefined();\n\n      const registeredHandler = (call?.[0] as Route).handler;\n\n      const mockCtx = {\n        req: {\n          method: \"GET\",\n          url: \"/api/test\",\n          headers: {},\n          params: {},\n          query: {},\n          body: {},\n        },\n        res: {\n          status: vi.fn().mockReturnThis(),\n          send: vi.fn().mockReturnThis(),\n          json: vi.fn().mockReturnThis(),\n          header: vi.fn().mockReturnThis(),\n          cookie: vi.fn().mockReturnThis(),\n        },\n      };\n\n      try {\n        await registeredHandler(mockCtx);\n      } catch (_e) {\n        // Ignore crashes\n      }\n\n      expect(mwCalled).toHaveBeenCalled();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tests/schema-helper.test.ts",
    "content": "import { describe, expect, it } from \"vitest\";\nimport { schema, t } from \"../src\";\n\ndescribe(\"Schema Helper\", () => {\n  it(\"should create schema definition with params\", () => {\n    const userSchema = schema({\n      params: t.object({\n        id: t.str().uuid(),\n      }),\n    });\n\n    expect(userSchema).toHaveProperty(\"params\");\n    expect(userSchema.params).toBeDefined();\n  });\n\n  it(\"should create schema definition with query\", () => {\n    const listSchema = schema({\n      query: t.object({\n        page: t.num().min(1).default(1),\n        limit: t.num().min(1).max(100).default(10),\n      }),\n    });\n\n    expect(listSchema).toHaveProperty(\"query\");\n    expect(listSchema.query).toBeDefined();\n  });\n\n  it(\"should create schema definition with body\", () => {\n    const createUserSchema = schema({\n      body: t.object({\n        name: t.str().min(1),\n        email: t.str().email(),\n        age: t.num().min(0).optional(),\n      }),\n    });\n\n    expect(createUserSchema).toHaveProperty(\"body\");\n    expect(createUserSchema.body).toBeDefined();\n  });\n\n  it(\"should create schema definition with headers\", () => {\n    const authSchema = schema({\n      headers: t.object({\n        authorization: t.str().min(1),\n      }),\n    });\n\n    expect(authSchema).toHaveProperty(\"headers\");\n    expect(authSchema.headers).toBeDefined();\n  });\n\n  it(\"should create complete schema definition\", () => {\n    const completeSchema = schema({\n      params: t.object({ id: t.str() }),\n      query: t.object({ include: t.str().optional() }),\n      body: t.object({ data: t.str() }),\n      headers: t.object({ \"content-type\": t.str() }),\n    });\n\n    expect(completeSchema.params).toBeDefined();\n    expect(completeSchema.query).toBeDefined();\n    expect(completeSchema.body).toBeDefined();\n    expect(completeSchema.headers).toBeDefined();\n  });\n\n  it(\"should pass through schema object unchanged\", () => {\n    const original = {\n      params: t.object({ id: t.str() }),\n      query: t.object({ page: t.num() }),\n    };\n\n    const result = schema(original);\n    expect(result).toBe(original);\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tests/server.test.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport { describe, it, expect, beforeEach, afterEach } from \"vitest\";\nimport { server, middleware, schema, t } from \"../src\";\n\ndescribe(\"Server\", () => {\n  let app: ReturnType<typeof server>;\n\n  beforeEach(() => {\n    app = server();\n  });\n\n  afterEach(() => {\n    if (app) {\n      app.close();\n    }\n  });\n\n  describe(\"Creation\", () => {\n    it(\"should create server instance\", () => {\n      expect(app).toBeDefined();\n      expect(typeof app.get).toBe(\"function\");\n      expect(typeof app.post).toBe(\"function\");\n      expect(typeof app.listen).toBe(\"function\");\n    });\n\n    it(\"should create server with options\", () => {\n      const appWithOptions = server({ port: 4000, host: \"127.0.0.1\" });\n      expect(appWithOptions).toBeDefined();\n      appWithOptions.close();\n    });\n  });\n\n  describe(\"Route Registration\", () => {\n    it(\"should register GET route\", () => {\n      expect(() => {\n        app.get(\"/\", (ctx) => {\n          ctx.res.send(\"hello\");\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register POST route\", () => {\n      expect(() => {\n        app.post(\"/users\", (ctx) => {\n          ctx.res.json({ success: true });\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register PUT route\", () => {\n      expect(() => {\n        app.put(\"/users/:id\", (ctx) => {\n          ctx.res.send(\"updated\");\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register DELETE route\", () => {\n      expect(() => {\n        app.delete(\"/users/:id\", (ctx) => {\n          ctx.res.sendStatus(204);\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register PATCH route\", () => {\n      expect(() => {\n        app.patch(\"/users/:id\", (ctx) => {\n          ctx.res.send(\"patched\");\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register route with schema\", () => {\n      const userSchema = schema({\n        params: t.object({ id: t.str().uuid() }),\n      });\n\n      expect(() => {\n        app.get(\"/users/:id\", [userSchema], (ctx) => {\n          ctx.res.json({ id: ctx.req.params.id });\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register route with middleware\", () => {\n      const auth = middleware((_, next) => {\n        next();\n      });\n\n      expect(() => {\n        app.get(\"/protected\", [auth], (ctx) => {\n          ctx.res.send(\"secret\");\n        });\n      }).not.toThrow();\n    });\n\n    it(\"should register route with multiple middlewares\", () => {\n      const auth = middleware((_, next) => next());\n      const logger = middleware((_, next) => next());\n\n      expect(() => {\n        app.get(\"/admin\", [auth, logger], (ctx) => {\n          ctx.res.send(\"admin\");\n        });\n      }).not.toThrow();\n    });\n  });\n\n  describe(\"Global Middleware\", () => {\n    it(\"should register global middleware\", () => {\n      const globalMw = middleware((_, next) => {\n        next();\n      });\n\n      expect(() => {\n        app.use(globalMw);\n      }).not.toThrow();\n    });\n\n    it(\"should register global middleware as function\", () => {\n      expect(() => {\n        app.use((_, next) => {\n          next();\n        });\n      }).not.toThrow();\n    });\n  });\n\n  describe(\"Extension\", () => {\n    it(\"should extend context\", () => {\n      const extendedApp = app.extend<{ db: { query: () => string } }>((ctx) => {\n        ctx.db = { query: () => \"result\" };\n      });\n\n      expect(extendedApp).toBeDefined();\n      extendedApp.close();\n    });\n\n    it(\"should extend context with return value\", () => {\n      const extendedApp = app.extend<{ user: { id: string } }>((_) => {\n        return { user: { id: \"123\" } };\n      });\n\n      expect(extendedApp).toBeDefined();\n      extendedApp.close();\n    });\n\n    it(\"should chain multiple extensions\", () => {\n      const extended = app\n        // biome-ignore lint/suspicious/noExplicitAny: ...\n        .extend<{ db: any }>((_) => ({ db: {} }))\n        // biome-ignore lint/suspicious/noExplicitAny: ...\n        .extend<{ cache: any }>((_) => ({ cache: {} }));\n\n      expect(extended).toBeDefined();\n      extended.close();\n    });\n  });\n\n  describe(\"Listen\", () => {\n    it(\"should have listen method\", () => {\n      expect(typeof app.listen).toBe(\"function\");\n    });\n\n    it(\"should have close method\", () => {\n      expect(typeof app.close).toBe(\"function\");\n    });\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tests/types.test.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport { describe, expectTypeOf, it } from \"vitest\";\nimport { server, schema, t, type Context } from \"../src\";\n\ndescribe(\"Type Safety\", () => {\n  it(\"should infer schema types correctly\", () => {\n    const userSchema = schema({\n      params: t.object({\n        id: t.str().uuid(),\n      }),\n      query: t.object({\n        limit: t.num().default(10),\n      }),\n      body: t.object({\n        name: t.str(),\n        email: t.str().email(),\n        age: t.num().optional(),\n      }),\n    });\n\n    type UserContext = Context<typeof userSchema>;\n\n    expectTypeOf<UserContext[\"req\"][\"params\"]>().toMatchTypeOf<{\n      id: string;\n    }>();\n\n    expectTypeOf<UserContext[\"req\"][\"query\"]>().toMatchTypeOf<{\n      limit: number;\n    }>();\n\n    expectTypeOf<UserContext[\"req\"][\"body\"]>().toMatchTypeOf<{\n      name: string;\n      email: string;\n      age?: number;\n    }>();\n  });\n\n  it(\"should infer optional fields\", () => {\n    const optionalSchema = schema({\n      query: t.object({\n        search: t.str().optional(),\n        page: t.num().default(1),\n      }),\n    });\n\n    type OptionalContext = Context<typeof optionalSchema>;\n\n    expectTypeOf<OptionalContext[\"req\"][\"query\"]>().toMatchTypeOf<{\n      search?: string;\n      page: number;\n    }>();\n  });\n\n  it(\"should infer array types\", () => {\n    const arraySchema = schema({\n      body: t.object({\n        tags: t.array(t.str()),\n        scores: t.array(t.num()),\n      }),\n    });\n\n    type ArrayContext = Context<typeof arraySchema>;\n\n    expectTypeOf<ArrayContext[\"req\"][\"body\"]>().toMatchTypeOf<{\n      tags: string[];\n      scores: number[];\n    }>();\n  });\n\n  it(\"should infer nested object types\", () => {\n    const nestedSchema = schema({\n      body: t.object({\n        user: t.object({\n          name: t.str(),\n          profile: t.object({\n            bio: t.str(),\n            avatar: t.str().url().optional(),\n          }),\n        }),\n      }),\n    });\n\n    type NestedContext = Context<typeof nestedSchema>;\n\n    expectTypeOf<NestedContext[\"req\"][\"body\"]>().toMatchTypeOf<{\n      user: {\n        name: string;\n        profile: {\n          bio: string;\n          avatar?: string;\n        };\n      };\n    }>();\n  });\n\n  it(\"should infer literal types\", () => {\n    const literalSchema = schema({\n      body: t.object({\n        role: t.union(\n          t.literal(\"admin\"),\n          t.literal(\"user\"),\n          t.literal(\"guest\"),\n        ),\n        status: t.literal(\"active\"),\n      }),\n    });\n\n    type LiteralContext = Context<typeof literalSchema>;\n\n    expectTypeOf<LiteralContext[\"req\"][\"body\"]>().toMatchTypeOf<{\n      role: \"admin\" | \"user\" | \"guest\";\n      status: \"active\";\n    }>();\n  });\n\n  it(\"should support extended context types\", () => {\n    interface Database {\n      // biome-ignore lint/suspicious/noExplicitAny: ...\n      query: (sql: string) => any;\n    }\n\n    const app = server().extend<{ db: Database }>((ctx) => {\n      ctx.db = { query: () => {} };\n    });\n\n    app.get(\"/\", (ctx) => {\n      expectTypeOf(ctx).toHaveProperty(\"db\");\n      expectTypeOf(ctx.db).toHaveProperty(\"query\");\n    });\n  });\n\n  it(\"should chain extension types\", () => {\n    interface DB {\n      query: () => void;\n    }\n    interface Cache {\n      get: () => void;\n    }\n\n    const app = server()\n      .extend<{ db: DB }>(() => ({ db: { query: () => {} } }))\n      .extend<{ cache: Cache }>(() => ({ cache: { get: () => {} } }));\n\n    app.get(\"/\", (ctx) => {\n      expectTypeOf(ctx).toHaveProperty(\"db\");\n      expectTypeOf(ctx).toHaveProperty(\"cache\");\n    });\n  });\n});\n"
  },
  {
    "path": "packages/kitojs/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"],\n  \"references\": [{ \"path\": \"../core\" }, { \"path\": \"../types\" }]\n}\n"
  },
  {
    "path": "packages/kitojs/tsdown.config.ts",
    "content": "import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n  entry: \"src/index.ts\",\n  outDir: \"dist\",\n\n  format: \"esm\",\n  minify: true,\n\n  dts: true,\n  tsconfig: \"tsconfig.json\",\n});\n"
  },
  {
    "path": "packages/kitojs/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/index.ts\"],\n  \"out\": \"docs\",\n  \"plugin\": [],\n  \"theme\": \"default\",\n  \"name\": \"Kito Framework\",\n  \"includeVersion\": true,\n  \"readme\": \"../../readme.md\",\n  \"categorizeByGroup\": true,\n  \"categoryOrder\": [\"Server\", \"Schemas\", \"Middleware\", \"Types\", \"*\"],\n  \"exclude\": [\n    \"**/node_modules/**\",\n    \"**/dist/**\",\n    \"**/tests/**\",\n    \"**/*.test.ts\",\n    \"**/server/analyzer.ts\",\n    \"**/server/request.ts\",\n    \"**/server/response.ts\"\n  ],\n  \"excludePrivate\": true,\n  \"excludeProtected\": true,\n  \"excludeInternal\": true,\n  \"cleanOutputDir\": true,\n  \"navigation\": {\n    \"includeCategories\": true,\n    \"includeGroups\": true\n  },\n  \"searchInComments\": true,\n  \"sort\": [\"source-order\", \"required-first\", \"alphabetical\"],\n  \"treatWarningsAsErrors\": false,\n  \"validation\": {\n    \"notExported\": true,\n    \"invalidLink\": true,\n    \"notDocumented\": false\n  }\n}\n"
  },
  {
    "path": "packages/kitojs/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: \"node\",\n    include: [\"tests/**/*.test.ts\"],\n    coverage: {\n      provider: \"v8\",\n      reporter: [\"text\", \"json\", \"html\"],\n      exclude: [\n        \"node_modules/\",\n        \"dist/\",\n        \"tests/\",\n        \"**/*.d.ts\",\n        \"**/*.config.ts\",\n      ],\n    },\n  },\n});\n"
  },
  {
    "path": "packages/readme.md",
    "content": "<img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-logo.svg\" width=\"200px\" align=\"right\" />\n\n# Kito - `packages`\n\nThis folder contains all the **modular packages** that make up the Kito framework.  \nIt is part of the **monorepo** managed with [`pnpm workspaces`](https://pnpm.io/workspaces).\n\nEach package is **independent**, versioned, and published under the `@kitojs/*` namespace (except `packages/kitojs`).\n\n---\n\n## 📂 Project structure\n\n```\n📂 packages/\n├── 📂 core\n│   ├── 📄 Cargo.toml\n│   ├── 📄 package.json\n│   ├── 📄 build.rs\n│   ├── 📄 .gitignore\n│   ├── 📂 src\n│   │   ├── 📄 lib.rs\n│   │   ├── 📄 server.rs\n│   │   ├── 📄 http.rs\n│   │   ├── 📂 http\n│   │   ├── 📂 server\n│   │   └── 📂 validation\n│   └── 📄 tsconfig.json\n├── 📂 kitojs\n│   ├── 📄 package.json\n│   ├── 📄 tsconfig.json\n│   ├── 📄 tsdown.config.ts\n│   ├── 📂 src\n│   │   ├── 📄 index.ts\n│   │   ├── 📂 server\n│   │   ├── 📂 helpers\n│   │   └── 📂 schemas\n│   └── 📄 .gitignore\n├── 📂 types\n│   ├── 📄 package.json\n│   ├── 📄 tsconfig.json\n│   ├── 📄 tsdown.config.ts\n│   ├── 📂 src\n│   │   ├── 📄 index.d.ts\n│   │   ├── 📄 context.d.ts\n│   │   ├── 📄 routes.d.ts\n│   │   ├── 📄 handlers.d.ts\n│   │   ├── 📂 schema\n│   │   └── 📂 http\n│   └── 📄 .gitignore\n└── 📄 readme.md\n```\n\n---\n\n## 📦 Packages\n\n### `@kitojs/kito-core`\n- The **Rust core** of the framework, exposing high-performance HTTP server functionality via [N-API](https://github.com/napi-rs/napi-rs).  \n- Responsibilities:\n  - Handling HTTP requests/responses efficiently.  \n  - Route and middleware execution.  \n  - Validation of request schemas and automatic error handling.  \n  - Integration with JS/TS through N-API bindings.  \n- This package is **fully written in Rust**, compiled to a native module, and serves as the runtime for all server logic.\n\n### `kitojs` (TypeScript library)\n- Main **TypeScript wrapper** for Kito, exposing the framework API to developers.  \n- Responsibilities:\n  - Create and configure servers (`app.get`, `app.post`, `app.use`, etc.).  \n  - Define route schemas, middleware, and static responses.  \n  - Utilities for schema building, validation, and server context.  \n  - Analyze route handlers for static/dynamic optimization.  \n- This package **depends on `kito-core`** for the runtime, but provides a developer-friendly API.\n\n### `@kitojs/types`\n- Standalone package containing **TypeScript type definitions** for Kito.  \n- Features:\n  - Type definitions for request, response, and server context.\n  - Route, schema, and handler typings.\n  - Shared types between core, CLI, and the TS library.\n- Designed to enable **full type safety** in TypeScript projects using Kito.\n\n---\n\n## 🛠️ Development workflow\n\nInside the monorepo, you can work on packages in isolation or all together:\n\n```bash\n# Build all packages\npnpm build\n\n# Build only a package\npnpm --filter @kitojs/pkg build\n````\n\nEach package is published independently but linked locally via the workspace.\n\n---\n"
  },
  {
    "path": "packages/types/.gitignore",
    "content": "dist/"
  },
  {
    "path": "packages/types/package.json",
    "content": "{\n  \"name\": \"@kitojs/types\",\n  \"version\": \"1.0.0-alpha.8\",\n  \"description\": \"TypeScript types for the Kito framework.\",\n  \"scripts\": {\n    \"build\": \"tsdown\"\n  },\n\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"tsdown\": \"^0.15.0\"\n  },\n\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/kitojs/kito.git\"\n  },\n  \"homepage\": \"https://kito.pages.dev\",\n  \"bugs\": {\n    \"url\": \"https://github.com/kitojs/kito/issues\"\n  },\n\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Nehuén\",\n    \"url\": \"https://github.com/nehu3n\"\n  },\n\n  \"type\": \"module\",\n  \"types\": \"dist/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.d.ts\"\n    }\n  },\n\n  \"files\": [\n    \"dist\",\n    \"readme.md\",\n    \"package.json\"\n  ]\n}\n"
  },
  {
    "path": "packages/types/src/context.d.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nimport type { KitoRequest } from \"./http/request\";\nimport type { KitoResponse } from \"./http/response\";\n\nimport type { SchemaDefinition, InferSchemaRequest } from \"./schema/base\";\n\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport interface KitoContext<TSchema extends SchemaDefinition = {}> {\n  req: KitoRequest & InferSchemaRequest<TSchema>;\n  res: KitoResponse;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport type Context<TSchema extends SchemaDefinition = {}> =\n  KitoContext<TSchema>;\n"
  },
  {
    "path": "packages/types/src/handlers.d.ts",
    "content": "import type { KitoContext } from \"./context\";\n\nexport type NextFunction = () => void | Promise<void>;\n\nexport type MiddlewareHandler<TSchema = unknown, TExtensions = unknown> = (\n  ctx: KitoContext<TSchema> & TExtensions,\n  next: NextFunction,\n) => void | Promise<void>;\n\nexport type RouteHandler<TSchema extends SchemaDefinition, TExtensions> = (\n  ctx: KitoContext<TSchema> & TExtensions,\n) => void | Promise<void> | unknown | Promise<unknown>;\n"
  },
  {
    "path": "packages/types/src/http/request.d.ts",
    "content": "export type CommonHeaderNames =\n  | \"accept\"\n  | \"accept-encoding\"\n  | \"accept-language\"\n  | \"authorization\"\n  | \"cache-control\"\n  | \"content-type\"\n  | \"content-length\"\n  | \"cookie\"\n  | \"host\"\n  | \"origin\"\n  | \"referer\"\n  | \"user-agent\"\n  | \"x-forwarded-for\"\n  | \"x-forwarded-host\"\n  | \"x-forwarded-proto\"\n  | \"x-requested-with\";\n\nexport interface RequestHeaders\n  extends Record<string, string | string[] | undefined> {\n  accept?: string;\n  \"accept-encoding\"?: string;\n  \"accept-language\"?: string;\n  authorization?: string;\n  \"cache-control\"?: string;\n  \"content-type\"?: string;\n  \"content-length\"?: string;\n  cookie?: string;\n  host?: string;\n  origin?: string;\n  referer?: string;\n  \"user-agent\"?: string;\n  \"x-forwarded-for\"?: string;\n  \"x-forwarded-host\"?: string;\n  \"x-forwarded-proto\"?: string;\n  \"x-requested-with\"?: string;\n}\n\nexport interface ParsedUrl {\n  pathname: string;\n  search: string | null;\n  query: Record<string, string | string[]>;\n}\n\nexport interface KitoRequest {\n  get method(): string;\n  get url(): string;\n\n  get headers(): RequestHeaders;\n\n  get body(): unknown;\n  get params(): Record<string, string>;\n  get query(): Record<string, string | string[]>;\n  get cookies(): Record<string, string>;\n  get pathname(): string;\n  get search(): string | null;\n  get protocol(): string;\n  get hostname(): string;\n  get ip(): string;\n  get ips(): string[];\n  get secure(): boolean;\n  get xhr(): boolean;\n  get originalUrl(): string;\n\n  header(name: CommonHeaderNames): string | undefined;\n  header(name: string): string | undefined;\n\n  queryParam(name: string): string | string[] | undefined;\n  param(name: string): string | undefined;\n  cookie(name: string): string | undefined;\n\n  json<T = unknown>(): T;\n  text(): string;\n\n  get raw(): {\n    body: Buffer;\n    headers: RequestHeaders;\n    url: string;\n    method: string;\n  };\n}\n"
  },
  {
    "path": "packages/types/src/http/response.d.ts",
    "content": "import type { InferType, SchemaType } from \"../schema/base\";\n\nexport type CommonResponseHeaderNames =\n  | \"content-type\"\n  | \"content-length\"\n  | \"cache-control\"\n  | \"etag\"\n  | \"expires\"\n  | \"last-modified\"\n  | \"location\"\n  | \"set-cookie\"\n  | \"access-control-allow-origin\"\n  | \"access-control-allow-methods\"\n  | \"access-control-allow-headers\"\n  | \"access-control-allow-credentials\"\n  | \"vary\"\n  | \"x-powered-by\"\n  | \"x-frame-options\"\n  | \"x-content-type-options\"\n  | \"strict-transport-security\";\n\nexport interface StreamWriter {\n  write(data: string | Buffer): void;\n\n  end(): void;\n  end(data: string | Buffer): void;\n}\n\nexport interface SSEWriter {\n  send(data: unknown, event?: string, id?: string, retry?: number): void;\n  comment(text: string): void;\n  close(): void;\n}\n\nexport interface KitoResponse<TResponseSchema = unknown> {\n  status(code: number): KitoResponse<TResponseSchema>;\n  sendStatus(code: number): void;\n\n  header(\n    name: CommonResponseHeaderNames,\n    value: string,\n  ): KitoResponse<TResponseSchema>;\n  header(name: string, value: string): KitoResponse<TResponseSchema>;\n\n  headers(\n    headers: Record<CommonResponseHeaderNames, string>,\n  ): KitoResponse<TResponseSchema>;\n  headers(headers: Record<string, string>): KitoResponse<TResponseSchema>;\n\n  append(\n    field: CommonResponseHeaderNames,\n    value: string,\n  ): KitoResponse<TResponseSchema>;\n  append(field: string, value: string): KitoResponse<TResponseSchema>;\n\n  set(\n    field: CommonResponseHeaderNames,\n    value: string,\n  ): KitoResponse<TResponseSchema>;\n  set(field: string, value: string): KitoResponse<TResponseSchema>;\n\n  get(field: CommonResponseHeaderNames): string | undefined;\n  get(field: string): string | undefined;\n\n  type(contentType: string): KitoResponse<TResponseSchema>;\n  contentType(contentType: string): KitoResponse<TResponseSchema>;\n\n  cookie(\n    name: string,\n    value: string,\n    options?: CookieOptions,\n  ): KitoResponse<TResponseSchema>;\n  clearCookie(\n    name: string,\n    options?: CookieOptions,\n  ): KitoResponse<TResponseSchema>;\n\n  end(): void;\n  send(\n    data: TResponseSchema extends SchemaType\n      ? InferType<TResponseSchema>\n      : unknown,\n  ): void;\n  json(\n    data: TResponseSchema extends SchemaType\n      ? InferType<TResponseSchema>\n      : unknown,\n  ): void;\n\n  text(data: string): void;\n  html(data: string): void;\n  redirect(url: string, code?: number): void;\n\n  location(url: string): KitoResponse<TResponseSchema>;\n\n  attachment(filename?: string): KitoResponse<TResponseSchema>;\n  download(path: string, filename?: string, options?: SendFileOptions): void;\n  sendFile(path: string, options?: SendFileOptions): void;\n\n  vary(field: string): KitoResponse<TResponseSchema>;\n  links(links: Record<string, string>): KitoResponse<TResponseSchema>;\n  format(obj: Record<string, () => void>): KitoResponse<TResponseSchema>;\n\n  stream(): StreamWriter;\n  sse(): SSEWriter;\n}\n\nexport interface CookieOptions {\n  domain?: string;\n  expires?: Date;\n  httpOnly?: boolean;\n  maxAge?: number;\n  path?: string;\n  secure?: boolean;\n  signed?: boolean;\n  sameSite?: boolean | \"lax\" | \"strict\" | \"none\";\n}\n\nexport interface SendFileOptions {\n  maxAge?: number;\n  root?: string;\n  lastModified?: boolean;\n  headers?: Record<string, string>;\n  dotfiles?: \"allow\" | \"deny\" | \"ignore\";\n  acceptRanges?: boolean;\n  cacheControl?: boolean;\n  immutable?: boolean;\n  etag?: boolean;\n}\n"
  },
  {
    "path": "packages/types/src/index.d.ts",
    "content": "// biome-ignore assist/source/organizeImports: ...\nexport * from \"./http/request\";\nexport * from \"./http/response\";\nexport * from \"./context\";\nexport * from \"./handlers\";\nexport * from \"./routes\";\nexport * from \"./router\";\nexport * from \"./server\";\n\nexport * from \"./schema/base\";\nexport * from \"./schema/string\";\nexport * from \"./schema/number\";\nexport * from \"./schema/boolean\";\nexport * from \"./schema/array\";\nexport * from \"./schema/object\";\nexport * from \"./schema/literal\";\nexport * from \"./schema/union\";\nexport * from \"./schema/jsonSchema\";\n"
  },
  {
    "path": "packages/types/src/router.d.ts",
    "content": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { MiddlewareDefinition, RouteChain } from \"./routes\";\nimport type { SchemaDefinition } from \"./schema/base\";\n\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport interface KitoRouterInstance<TExtensions = {}> {\n  use(\n    middleware: MiddlewareDefinition | MiddlewareHandler,\n  ): KitoRouterInstance<TExtensions>;\n\n  mount(\n    path: string,\n    router: KitoRouterInstance<TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    path: string,\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): KitoRouterInstance<TExtensions>;\n\n  route(path: string): RouteChain<TExtensions>;\n  route(\n    path: string,\n    middlewares: MiddlewareDefinition[] | MiddlewareDefinition,\n  ): RouteChain<TExtensions>;\n}\n"
  },
  {
    "path": "packages/types/src/routes.d.ts",
    "content": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { SchemaDefinition } from \"./schema/base\";\nimport type { KitoRouterInstance } from \"./router\";\n\nexport type HttpMethod =\n  | \"GET\"\n  | \"POST\"\n  | \"PUT\"\n  | \"DELETE\"\n  | \"PATCH\"\n  | \"HEAD\"\n  | \"OPTIONS\"\n  | \"TRACE\";\n\nexport interface RouteDefinition<TExtensions = unknown> {\n  method: HttpMethod;\n  path: string;\n  middlewares: (MiddlewareDefinition | SchemaDefinition)[];\n  handler: RouteHandler<SchemaDefinition, TExtensions>;\n}\n\nexport interface MiddlewareDefinition {\n  type: \"function\" | \"schema\";\n  handler?: MiddlewareHandler;\n  schema?: SchemaDefinition;\n  global: boolean;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport type RouteChain<TExtensions = {}> = {\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  get<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  post<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  put<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  delete<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  patch<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  head<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    middlewares:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema),\n    handler: RouteHandler<TSchema, TExtensions>,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    handler: RouteHandler<TSchema, TExtensions>,\n    schema: TSchema,\n  ): RouteChain<TExtensions>;\n  // biome-ignore lint/complexity/noBannedTypes: ...\n  options<TSchema extends SchemaDefinition = {}>(\n    middlewaresOrHandler:\n      | (MiddlewareDefinition | TSchema)[]\n      | (MiddlewareDefinition | TSchema)\n      | RouteHandler<TSchema, TExtensions>,\n    handlerOrSchema?: RouteHandler<TSchema, TExtensions> | TSchema,\n  ): RouteChain<TExtensions>;\n\n  end(): KitoRouterInstance<TExtensions>;\n};\n"
  },
  {
    "path": "packages/types/src/schema/array.d.ts",
    "content": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface ArraySchema<T extends SchemaType> extends SchemaType {\n  _type: InferType<T>[];\n  min(length: number): ArraySchema<T>;\n  max(length: number): ArraySchema<T>;\n  length(length: number): ArraySchema<T>;\n  optional(): OptionalArraySchema<T>;\n  default(value: InferType<T>[]): DefaultArraySchema<T>;\n}\n\nexport interface OptionalArraySchema<T extends SchemaType>\n  extends Omit<ArraySchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: InferType<T>[]): DefaultArraySchema<T>;\n}\n\nexport interface DefaultArraySchema<T extends SchemaType>\n  extends Omit<ArraySchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: InferType<T>[];\n}\n"
  },
  {
    "path": "packages/types/src/schema/base.d.ts",
    "content": "import type { RequestHeaders } from \"../http/request\";\n\nexport interface SchemaDefinition {\n  params?: SchemaType;\n  query?: SchemaType;\n  body?: SchemaType;\n  headers?: SchemaType;\n  response?: ResponseSchemaDefinition;\n}\n\nexport interface ResponseSchemaDefinition {\n  [statusCode: number]: SchemaType;\n}\n\nexport type InferSchemaRequest<T extends SchemaDefinition> = T extends {\n  __jsonSchemaInfer: infer J;\n}\n  ? J\n  : {\n      params: T[\"params\"] extends SchemaType\n        ? InferType<T[\"params\"]>\n        : Record<string, string>;\n      query: T[\"query\"] extends SchemaType\n        ? InferType<T[\"query\"]>\n        : Record<string, string | string[]>;\n      body: T[\"body\"] extends SchemaType ? InferType<T[\"body\"]> : unknown;\n      headers: T[\"headers\"] extends SchemaType\n        ? InferType<T[\"headers\"]>\n        : RequestHeaders;\n    };\n\nexport interface SchemaType {\n  _type: unknown;\n  _optional: boolean;\n  _default?: unknown;\n  // biome-ignore lint/suspicious/noExplicitAny: ...\n  _serialize?(): any;\n}\n\nexport type InferType<T extends SchemaType> = T extends { _default: infer D }\n  ? D\n  : T extends { _optional: true }\n    ? T[\"_type\"] | undefined\n    : T[\"_type\"];\n"
  },
  {
    "path": "packages/types/src/schema/boolean.d.ts",
    "content": "import type { SchemaType } from \"./base\";\n\nexport interface BooleanSchema extends SchemaType {\n  _type: boolean;\n  optional(): OptionalBooleanSchema;\n  default(value: boolean): DefaultBooleanSchema;\n}\n\nexport interface OptionalBooleanSchema\n  extends Omit<BooleanSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: boolean): DefaultBooleanSchema;\n}\n\nexport interface DefaultBooleanSchema\n  extends Omit<BooleanSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: boolean;\n}\n"
  },
  {
    "path": "packages/types/src/schema/jsonSchema.d.ts",
    "content": "type StringFormat = \"email\" | \"uuid\" | \"uri\" | \"date-time\";\n\ninterface BaseJSONSchema {\n  description?: string;\n  default?: unknown;\n}\n\nexport interface JSONSchemaString extends BaseJSONSchema {\n  type: \"string\";\n  minLength?: number;\n  maxLength?: number;\n  pattern?: string;\n  format?: StringFormat;\n  enum?: readonly string[];\n  const?: string;\n}\n\nexport interface JSONSchemaNumber extends BaseJSONSchema {\n  type: \"number\" | \"integer\";\n  minimum?: number;\n  maximum?: number;\n  enum?: readonly number[];\n  const?: number;\n}\n\nexport interface JSONSchemaBoolean extends BaseJSONSchema {\n  type: \"boolean\";\n  const?: boolean;\n}\n\nexport interface JSONSchemaArray extends BaseJSONSchema {\n  type: \"array\";\n  items: JSONSchema;\n  minItems?: number;\n  maxItems?: number;\n}\n\nexport interface JSONSchemaObject extends BaseJSONSchema {\n  type: \"object\";\n  properties: Record<string, JSONSchema>;\n  required?: readonly string[];\n}\n\nexport type JSONSchema =\n  | JSONSchemaString\n  | JSONSchemaNumber\n  | JSONSchemaBoolean\n  | JSONSchemaArray\n  | JSONSchemaObject;\n\ntype InferString<T extends JSONSchemaString> = T extends { const: infer C }\n  ? C\n  : T extends { enum: infer E }\n    ? E extends readonly (infer U)[]\n      ? U\n      : never\n    : string;\n\ntype InferNumber<T extends JSONSchemaNumber> = T extends { const: infer C }\n  ? C\n  : T extends { enum: infer E }\n    ? E extends readonly (infer U)[]\n      ? U\n      : never\n    : number;\n\ntype InferBoolean<T extends JSONSchemaBoolean> = T extends { const: infer C }\n  ? C\n  : boolean;\n\ntype InferArray<T extends JSONSchemaArray> = T extends { items: infer I }\n  ? I extends JSONSchema\n    ? InferJSONSchemaType<I>[]\n    : never\n  : never;\n\ntype InferObject<T extends JSONSchemaObject> = T extends {\n  properties: infer P;\n  required?: infer R;\n}\n  ? P extends Record<string, JSONSchema>\n    ? R extends readonly string[]\n      ? {\n          [K in keyof P as K extends R[number]\n            ? K\n            : never]: P[K] extends JSONSchema\n            ? InferJSONSchemaType<P[K]>\n            : never;\n        } & {\n          [K in keyof P as K extends R[number]\n            ? never\n            : K]?: P[K] extends JSONSchema ? InferJSONSchemaType<P[K]> : never;\n        }\n      : {\n          [K in keyof P]?: P[K] extends JSONSchema\n            ? InferJSONSchemaType<P[K]>\n            : never;\n        }\n    : never\n  : never;\n\nexport type InferJSONSchemaType<T> = T extends { default: infer D }\n  ? D\n  : T extends JSONSchemaString\n    ? InferString<T>\n    : T extends JSONSchemaNumber\n      ? InferNumber<T>\n      : T extends JSONSchemaBoolean\n        ? InferBoolean<T>\n        : T extends JSONSchemaArray\n          ? InferArray<T>\n          : T extends JSONSchemaObject\n            ? InferObject<T>\n            : never;\n\nexport interface JSONSchemaDefinition {\n  params?: JSONSchemaObject;\n  query?: JSONSchemaObject;\n  body?: JSONSchema;\n  headers?: JSONSchemaObject;\n  response?: {\n    [statusCode: number]: JSONSchema;\n  };\n}\n\nexport type InferJSONSchemaRequest<T extends JSONSchemaDefinition> = {\n  params: T[\"params\"] extends JSONSchemaObject\n    ? InferJSONSchemaType<T[\"params\"]>\n    : Record<string, string>;\n  query: T[\"query\"] extends JSONSchemaObject\n    ? InferJSONSchemaType<T[\"query\"]>\n    : Record<string, string | string[]>;\n  body: T[\"body\"] extends JSONSchema ? InferJSONSchemaType<T[\"body\"]> : unknown;\n  headers: T[\"headers\"] extends JSONSchemaObject\n    ? InferJSONSchemaType<T[\"headers\"]>\n    : Record<string, string | string[]>;\n};\n"
  },
  {
    "path": "packages/types/src/schema/literal.d.ts",
    "content": "import type { SchemaType } from \"./base\";\n\nexport interface LiteralSchema<T extends string | number | boolean>\n  extends SchemaType {\n  _type: T;\n  optional(): OptionalLiteralSchema<T>;\n  default(value: T): DefaultLiteralSchema<T>;\n}\n\nexport interface OptionalLiteralSchema<T extends string | number | boolean>\n  extends Omit<LiteralSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: T): DefaultLiteralSchema<T>;\n}\n\nexport interface DefaultLiteralSchema<T extends string | number | boolean>\n  extends Omit<LiteralSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: T;\n}\n"
  },
  {
    "path": "packages/types/src/schema/number.d.ts",
    "content": "import type { SchemaType } from \"./base\";\n\nexport interface NumberSchema extends SchemaType {\n  _type: number;\n  min(value: number): NumberSchema;\n  max(value: number): NumberSchema;\n  int(): NumberSchema;\n  positive(): NumberSchema;\n  negative(): NumberSchema;\n  optional(): OptionalNumberSchema;\n  default(value: number): DefaultNumberSchema;\n}\n\nexport interface OptionalNumberSchema\n  extends Omit<NumberSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: number): DefaultNumberSchema;\n}\n\nexport interface DefaultNumberSchema\n  extends Omit<NumberSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: number;\n}\n"
  },
  {
    "path": "packages/types/src/schema/object.d.ts",
    "content": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface ObjectSchema<T extends Record<string, SchemaType>>\n  extends SchemaType {\n  _type: { [K in keyof T]: InferType<T[K]> };\n  shape: T;\n  optional(): OptionalObjectSchema<T>;\n  default(value: { [K in keyof T]: InferType<T[K]> }): DefaultObjectSchema<T>;\n}\n\nexport interface OptionalObjectSchema<T extends Record<string, SchemaType>>\n  extends Omit<ObjectSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: { [K in keyof T]: InferType<T[K]> }): DefaultObjectSchema<T>;\n}\n\nexport interface DefaultObjectSchema<T extends Record<string, SchemaType>>\n  extends Omit<ObjectSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: { [K in keyof T]: InferType<T[K]> };\n}\n"
  },
  {
    "path": "packages/types/src/schema/string.d.ts",
    "content": "import type { SchemaType } from \"./base\";\n\nexport interface StringSchema extends SchemaType {\n  _type: string;\n  min(length: number): StringSchema;\n  max(length: number): StringSchema;\n  length(length: number): StringSchema;\n  email(): StringSchema;\n  url(): StringSchema;\n  uuid(): StringSchema;\n  regex(pattern: RegExp): StringSchema;\n  optional(): OptionalStringSchema;\n  default(value: string): DefaultStringSchema;\n}\n\nexport interface OptionalStringSchema\n  extends Omit<StringSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: string): DefaultStringSchema;\n}\n\nexport interface DefaultStringSchema\n  extends Omit<StringSchema, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: string;\n}\n"
  },
  {
    "path": "packages/types/src/schema/union.d.ts",
    "content": "import type { InferType, SchemaType } from \"./base\";\n\nexport interface UnionSchema<T extends SchemaType[]> extends SchemaType {\n  _type: InferType<T[number]>;\n  optional(): OptionalUnionSchema<T>;\n  default(value: InferType<T[number]>): DefaultUnionSchema<T>;\n}\n\nexport interface OptionalUnionSchema<T extends SchemaType[]>\n  extends Omit<UnionSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  default(value: InferType<T[number]>): DefaultUnionSchema<T>;\n}\n\nexport interface DefaultUnionSchema<T extends SchemaType[]>\n  extends Omit<UnionSchema<T>, \"optional\" | \"default\"> {\n  _optional: true;\n  _default: InferType<T[number]>;\n}\n"
  },
  {
    "path": "packages/types/src/server.d.ts",
    "content": "import type { MiddlewareHandler, RouteHandler } from \"./handlers\";\nimport type { MiddlewareDefinition, RouteChain } from \"./routes\";\nimport type { SchemaDefinition } from \"./schema/base\";\nimport type { KitoRouterInstance } from \"./router\";\n\nexport interface ServerOptions {\n  port?: number;\n  host?: string;\n  unixSocket?: string;\n  trustProxy?: boolean;\n  maxRequestSize?: number;\n  timeout?: number;\n  reusePort?: boolean;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: ...\nexport interface KitoServerInstance<TExtensions = {}>\n  extends KitoRouterInstance<TExtensions> {\n  listen(callback?: () => void): Promise<ServerOptions>;\n  listen(port?: number, callback?: () => void): Promise<ServerOptions>;\n  listen(\n    port?: number,\n    host?: string,\n    callback?: () => void,\n  ): Promise<ServerOptions>;\n  listen(options: ServerOptions, callback?: () => void): Promise<ServerOptions>;\n\n  close(): void;\n}\n"
  },
  {
    "path": "packages/types/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"emitDeclarationOnly\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/types/tsdown.config.ts",
    "content": "import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n  entry: \"src/index.d.ts\",\n  outDir: \"dist\",\n\n  format: \"esm\",\n  minify: true,\n\n  dts: true,\n  tsconfig: \"tsconfig.json\",\n});\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - packages/*\n  - examples\n  - bench\n\nonlyBuiltDependencies:\n  - skia-canvas"
  },
  {
    "path": "readme.md",
    "content": "<div align=\"center\">\n  <img src=\"https://github.com/kitojs/.github/blob/882f94e7c1bb1c463ad475539aa4d53a2eeef1d5/assets/kito-banner.svg\" width=\"220px\" />\n  \n  <br />\n  <br />\n  \n  <p>\n    <strong>High-performance</strong>, fully <strong>type-safe</strong>, and modern web framework for <strong>TypeScript</strong>.  \n    Powered by <strong>Rust</strong> for extreme speed and low memory usage.\n  </p>\n</div>\n\n---\n\n- **Extreme performance** – Rust core optimized for extreme speed & efficiency. **See the [benchmarks](https://github.com/kitojs/kito/tree/main/bench).**\n- **Type-safe** – full TypeScript support with end-to-end safety and exceptional DX.\n- **Schema validation** – built-in validation with zero bloat.  \n- **Middleware system** – composable and flexible like you expect.\n- **Cross-platform** – runs on Node.js, Bun, and Deno.  \n\n---\n\n## 🚀 Quick Start\n\nYou can add **Kito** to an existing project:\n\n```bash\npnpm add kitojs\n\n# Or: npm/yarn/bun add kitojs\n# Or: deno add npm:kitojs\n```\n\nOr create a new project instantly with the [official starter](https://github.com/kitojs/create-kitojs):\n\n```bash\npnpm create kitojs\n\n# Or: npm/yarn/bun create kitojs\n# Or: deno init --npm kitojs\n```\n\n### Minimal Example\n\n```ts\nimport { server } from \"kitojs\";\nconst app = server();\n\napp.get(\"/\", ({ res }) => {\n  res.send(\"hello world!\");\n});\n\napp.listen(3000);\n```\n\n<details>\n  <summary><strong>Fluent style</strong></summary>\n\n  Kito also supports fluent style. You can chain all methods. **See the examples [here](https://github.com/kitojs/kito/tree/main/examples/fluent).**\n\n  ```ts\n  import { server } from \"kitojs\";\n\n  server()\n    .get(\"/\", ({ res }) => res.send(\"hello world!\"))\n    .listen(3000);\n  ```\n</details>\n\n---\n\n## 📚 Documentation\n\nFull docs available at the [**official website**](https://kito.pages.dev).\nYou can also explore ready-to-run [examples](https://github.com/kitojs/kito/tree/main/examples).\n\n---\n\n## 🤝 Contributing\n\nWe 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.\n\n---\n\n## 📄 License\n\nLicensed under the [MIT License](https://github.com/kitojs/kito/blob/main/license).\n\n---\n\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kitojs/kito)\n"
  },
  {
    "path": "rust-toolchain.toml",
    "content": "[toolchain]\nchannel = \"stable\"\ncomponents = [\"clippy\", \"rustfmt\", \"rust-analyzer\"]"
  },
  {
    "path": "rustfmt.toml",
    "content": "edition = \"2024\"\n\nmax_width = 100\n\nhard_tabs = false\ntab_spaces = 4\n\nnewline_style = \"Unix\"\nuse_small_heuristics = \"Max\"\nreorder_imports = true\nreorder_modules = true\n\nmerge_derives = true"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"outDir\": \"dist\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true,\n    \"composite\": true,\n    \"resolveJsonModule\": true,\n\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@kitojs/kito-core\": [\"packages/core/src\"],\n      \"@kitojs/types\": [\"packages/types/src\"],\n      \"kitojs\": [\"packages/kitojs/src\"]\n    }\n  }\n}\n"
  }
]