{"id":33926141,"url":"https://github.com/nukopy/engawa","last_synced_at":"2026-06-10T09:31:13.496Z","repository":{"id":323635842,"uuid":"1093698006","full_name":"nukopy/engawa","owner":"nukopy","description":"Chat application in your terminal","archived":false,"fork":false,"pushed_at":"2025-11-13T16:42:06.000Z","size":401,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-25T20:23:14.265Z","etag":null,"topics":["axum","chat","rust","websocket"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nukopy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-10T18:06:42.000Z","updated_at":"2025-11-13T16:38:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nukopy/engawa","commit_stats":null,"previous_names":["nukopy/chat-app-rs","nukopy/chat-app-layered-ddd-rs","nukopy/engawa"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/nukopy/engawa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukopy%2Fengawa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukopy%2Fengawa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukopy%2Fengawa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukopy%2Fengawa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nukopy","download_url":"https://codeload.github.com/nukopy/engawa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nukopy%2Fengawa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34146871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axum","chat","rust","websocket"],"created_at":"2025-12-12T10:05:36.567Z","updated_at":"2026-06-10T09:31:13.447Z","avatar_url":"https://github.com/nukopy.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Engawa\n\n[![Crates.io version badge][crates-badge]][crates-url]\n[![MIT license badge][mit-badge]][mit-url]\n[![GitHub Actions workflow badge - CI][github-actions-badge-ci]][github-actions-url-ci]\n\n[crates-badge]: https://img.shields.io/crates/v/engawa-server.svg\n[crates-url]: https://crates.io/crates/engawa-server\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/nukopy/engawa/blob/main/LICENSE\n[github-actions-badge-ci]: https://github.com/nukopy/engawa/actions/workflows/ci.yml/badge.svg?branch=main\n[github-actions-url-ci]: https://github.com/nukopy/engawa/actions/workflows/ci.yml?query=branch:main\n\nLayered Architecture / DDD を採用した、Rust + Axum + WebSocket のチャットアプリ Engawa (\"縁側\" in Japanese)\n\n## プロジェクト構成\n\n本プロジェクトは Cargo Workspace を使用した複数パッケージ構成です：\n\n- **packages/shared**: 共通ユーティリティ（時刻管理、ロガー）\n- **packages/server**: サーバアプリケーション（Layered Architecture による4層構造）\n- **packages/client**: CLIクライアントアプリケーション\n\n詳細は [AGENTS.md](./AGENTS.md) および [ソフトウェアアーキテクチャドキュメント](./docs/documentations/software-architecture.md) を参照してください。\n\n## 技術スタック\n\n- Rust 1.90.0\n- Axum 0.8.6\n\n## システム構成\n\n```mermaid\ngraph TD\n    %% 登場人物\n    Client1[Client 1（CLI Application）]\n    Client2[Client 2]\n    Client3[Client 3]\n    Server[Server]\n\n    %% データフロー\n    Client1 --\u003e| メッセージ送信 | Server\n    Server --\u003e| メッセージ受信 | Client2\n    Server --\u003e| メッセージ受信 | Client3\n```\n\n## 機能\n\n- **リアルタイムチャット**:\n  - クライアント間でメッセージを送受信（送信者自身には送信されない）\n  - メッセージは送信者以外の全クライアントにブロードキャスト\n- **参加者管理**:\n  - 接続時に現在の参加者一覧を表示（`room-connected`）\n  - 新規参加者の入室通知（`participant-joined`）\n  - 参加者の退室通知（`participant-left`）\n  - 各参加者の入室タイムスタンプ（ミリ秒精度、JST）\n- **接続管理**:\n  - ユニークな `client_id` による識別\n  - 重複 `client_id` の接続拒否（HTTP 409 Conflict）\n  - 自動再接続機能（5秒間隔、最大 5 回）\n    - TODO: exponential backoff にする\n- **サーバ機能**:\n  - グレースフルシャットダウン（Ctrl+C / SIGTERM）\n  - クライアント接続状態の管理\n- **メッセージタイプ**:\n  - `room-connected`: 初回接続時の参加者一覧\n  - `participant-joined`: 参加通知\n  - `participant-left`: 退出通知\n  - `chat`: チャットメッセージ\n\n## サービス概要\n\n- `bin/server`: WebSocket チャットサーバ。接続中のクライアント間でメッセージをブロードキャストします（送信者自身には送信されません）\n- `bin/client`: インタラクティブなチャットクライアント。ユニークな `client_id` で接続し、再接続機能を持ちます\n\n## Requirements\n\n- Rust 1.90.0\n- [Task](https://taskfile.dev/docs/installation) 3.45.5\n\n## 開発\n\n### format\n\n```sh\ncargo fmt\n```\n\n### lint\n\n```sh\n# Clippy（lint）\ncargo clippy --workspace --all-targets --all-features\n\n# フォーマット\ncargo fmt\n```\n\n### テスト\n\n```sh\n# workspace 全体のテスト\ncargo test --workspace\n# cargo test でも OK\n\n# 個別パッケージのテスト\ncargo test -p server\ncargo test -p client\ncargo test -p shared\n```\n\n### ビルド\n\n```sh\n# workspace 全体をビルド\ncargo build --workspace\n# cargo build でも OK\n\n# 個別パッケージのビルド\ncargo build -p server\ncargo build -p client\ncargo build -p shared\n```\n\n### 実行\n\n#### サーバの起動\n\n```sh\ncargo run -p server --bin server\n\n# ポート指定\ncargo run -p server --bin server -- --p 8080\n```\n\nhelp\n\n```sh\ncargo run -p server --bin server -- --help\n```\n\n#### クライアントの起動\n\n```sh\ncargo run -p client --bin client -- --client-id alice\n\n# サーバURL指定\ncargo run -p client --bin client -- --client-id alice --url ws://127.0.0.1:8080/ws\n\n# 別ターミナルで起動\ncargo run -p client --bin client -- --client-id bob\n```\n\nhelp\n\n```sh\ncargo run -p client --bin client -- --help\n```\n\n## リリース to crates.io\n\n参考：[The Cargo Book - Publishing Commands](https://doc.rust-lang.org/cargo/commands/publishing-commands.html)\n\n### crates.io へのログイン：`cargo login`\n\nターミナルで `cargo login` 実行後、[https://crates.io/me](https://crates.io/me) へ飛び、トークンを生成する。その後、ターミナルにトークンを貼り付けて Enter を入力し、`Login token for crates-io saved` と表示されれば OK。\n\n```sh\ncargo login\n# please paste the token found on https://crates.io/me below\n#       Login token for `crates-io` saved\n```\n\n### crates.io へのリリース：`cargo publish`\n\n- `cargo publish`\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e 依存しているパッケージは後でリリースする必要がある。\n\u003e 依存先が crates.io に登録されていない場合、`cargo publish` が失敗する。\n\n```sh\ncargo publish --dry-run\n\n# 依存関係を自動で解決して publish する\ncargo publish\n\n# 依存順序を守って publish する\ncargo publish -p engawa-shared\ncargo publish -p engawa-server\ncargo publish -p engawa-client\n```\n\n- Git tagging\n  - `cargo publish` が失敗する場合があるので、`cargo publish` の後にリリース時点のコミットに tag を付与する。\n\n```sh\n# git tag \u0026 push\ngit commit --allow-empty -m \"Release v0.0.1 :tada:\"\ngit tag -a v0.0.1 -m \"Release v0.0.1 :tada:\"\ngit push origin v0.0.1\n\n# untag\ngit tag -d v0.0.1\ngit push origin :v0.0.1\n```\n\n## Note\n\n### Task の使い方\n\n- format / lint / check / test\n\n```sh\ntask fmt\ntask lint\ntask check\ntask test\n```\n\n- コミット前の全チェック\n\n```sh\ntask ci\n```\n\n- サーバの起動\n\n```sh\ntask run-server\n\n# host, port 指定\ntask run-server HOST=127.0.0.1 PORT=8080\n```\n\n- クライアントの起動\n\n```sh\ntask run-client\n\n# client-id, URL 指定\ntask run-client CLIENT_ID=alice URL=ws://127.0.0.1:8080/ws\n\n# デバッグ用途\ntask run-client-alice\ntask run-client-bob\n```\n\n- タスク一覧\n\n```sh\ntask\n```\n\n- タスクの詳細\n\n```sh\ntask --summary \u003ctask-name\u003e\n\n# 例\ntask --summary run-server\ntask --summary run-client\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnukopy%2Fengawa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnukopy%2Fengawa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnukopy%2Fengawa/lists"}