Skip to content

Commit 8da3be6

Browse files
authored
Merge pull request #7 from dropdevrahul/redesign-shadcn-ui
Redesign UI with shadcn/ui (Tailwind + Radix) and add Go tests
2 parents c45133a + dd87422 commit 8da3be6

35 files changed

Lines changed: 3868 additions & 704 deletions

AGENTS.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# AGENTS.md — Hypr Repository Quick Reference
2+
3+
## What is this?
4+
Hypr is a **desktop REST API client** (like Postman/Insomnia) built with **Wails v2.5.1** (Go backend + React/TypeScript frontend). It runs on macOS, Windows, and Linux.
5+
6+
## Key commands
7+
8+
| Command | What it does |
9+
|---------|-------------|
10+
| `wails dev` | Live dev mode — Vite HMR frontend + Go backend. Opens browser on `localhost:34115`. |
11+
| `wails build` | Production build — outputs a native executable (name: `hypr`, per `wails.json`). |
12+
| `go mod tidy` | Sync Go dependencies. Wails calls `npm install` automatically. |
13+
| `wails doctor` | Check Wails toolchain prerequisites (native deps, etc.). |
14+
15+
**There are no tests in this repo.** There is no `go test` or `npm test` to run.
16+
17+
## Project structure
18+
19+
```
20+
hypr/
21+
main.go — Entry point. Embeds `frontend/dist`, creates Wails window (1280×1080).
22+
app.go — Go HTTP client logic: `MakeRequest()`, `RunCurl()`, `RequestResult` struct.
23+
parse_curl.go — Curl-to-request parser. Uses `go-shellwords` to tokenize curl strings.
24+
export.go — Exports request/response to JSON via native save dialog.
25+
frontend/
26+
src/
27+
App.tsx — Main React component. All UI: method selector, URL, headers, body, response.
28+
main.tsx — React 18 entry point, renders `<App />`.
29+
vite.config.ts — Minimal Vite config (React plugin only).
30+
tsconfig.json — TypeScript strict mode, `noEmit: true`, JSX react-jsx.
31+
wails.json — Wails config: frontend install/build hooks, output filename.
32+
go.mod — Go module: `module changeme` (⚠️ not renamed from default).
33+
```
34+
35+
## Architecture notes
36+
37+
- **Go module name is `changeme`** (`go.mod:1`). This is the default placeholder — it has not been renamed. If you import this module elsewhere, update it.
38+
- **Go version: 1.18** (`go.mod:2`). No newer Go features (generics, etc.) are used.
39+
- **Wails binds `App` struct** (`main.go:31`) to the frontend. All Go methods called from React (`MakeRequest`, `RunCurl`, `Export`) are on this struct.
40+
- **Frontend auto-build**: Wails runs `npm run build` (which does `tsc && vite build`) before producing the final binary. The `frontend/dist` directory is embedded into the Go binary via `//go:embed all:frontend/dist`.
41+
- **No CI/CD workflows** exist in this repo (no `.github/workflows/`).
42+
- **No linting, formatting, or typecheck scripts** — just `tsc` via the build step.
43+
44+
## Common gotchas
45+
46+
- **First-time setup**: Run `wails doctor` before `wails dev`. Wails needs platform-specific native toolchains (e.g., WebKit on Linux, Safari frameworks on macOS).
47+
- **Module name mismatch**: `go.mod` says `module changeme`. The `go:embed` path in `main.go` references `frontend/dist` — this works because Wails manages the build. But the Go module name should be updated if this project is published or imported.
48+
- **No hot-reload for Go code**: `wails dev` only hot-reloads the frontend (Vite HMR). Go changes require a restart.
49+
- **Curl parser limitations** (`parse_curl.go`): Handles basic curl flags (`-X`, `-H`, `-d`, `-A`, `-u`, `-I`, `-b`). Does not handle `--data-binary`, `--data-urlencode`, or complex multi-part uploads.

CLAUDE.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What this is
6+
7+
Hypr is a desktop REST API client (like Postman/Insomnia) built with **Wails v2** (Go backend + React/TypeScript frontend). The Go HTTP client does the actual network calls; the React app is the UI.
8+
9+
## Commands
10+
11+
| Command | What it does |
12+
|---------|-------------|
13+
| `wails dev` | Live dev mode — Vite HMR for the frontend + Go backend. Also serves a browser dev server at `http://localhost:34115` where Go methods are callable from devtools. |
14+
| `wails build` | Production build — embeds `frontend/dist` and outputs a native executable named `hypr` (per `wails.json`). |
15+
| `go mod tidy` | Sync Go dependencies. |
16+
| `wails doctor` | Check the Wails toolchain / native prerequisites. Run this before `wails dev` on a fresh machine. |
17+
| `npm run build` (in `frontend/`) | `tsc && vite build`. Wails runs this automatically during `wails build`; run it manually to typecheck. |
18+
19+
Go has unit tests — run them with `go test ./...` (curl parser and HTTP helpers; see `parse_curl_test.go`, `app_test.go`). The frontend has **no test runner**; its only check is `tsc` via the build. There is **no lint/format/CI** config.
20+
21+
**Go changes are not hot-reloaded**`wails dev` only HMRs the frontend. Restart `wails dev` after editing Go.
22+
23+
## Architecture
24+
25+
The frontend↔backend boundary is the only non-obvious part. Wails binds the Go `App` struct (`main.go`, `Bind: []interface{}{app}`) and code-generates TypeScript wrappers into `frontend/wailsjs/`. The React app imports those wrappers (`../wailsjs/go/main/App`) and calls Go methods as promises.
26+
27+
**Three bound Go methods** (all on `App`, all callable from React):
28+
- `MakeRequest(url, method, body, headers)` — builds and sends the HTTP request via the shared `http.Client` (50s timeout, created in `startup`), returns a `RequestResult`. JSON response bodies are pretty-indented server-side.
29+
- `RunCurl(curl)` — parses a curl string into a `Request`, then calls `MakeRequest`.
30+
- `Export(req, reqHeaders, reqBodies, result)` — opens a native save dialog and writes the request/response as JSON.
31+
32+
`RequestResult` (`app.go`) is the single response shape returned to the UI: `Body`, `HeadersStr` (newline-joined response headers), `Error`, plus echoed-back request fields. Errors are returned **inside** `RequestResult.Error`, not as a thrown/rejected promise — the UI checks `result.Error`.
33+
34+
**Curl parsing** (`parse_curl.go`): a hand-written state machine over `go-shellwords` tokens. Supports `-X/--request`, `-H/--header`, `-d/--data[-ascii|-raw]`, `-A/--user-agent`, `-u/--user` (→ Basic auth), `-I/--head`, `-b/--cookie`. Does **not** handle `--data-binary`, `--data-urlencode`, or multipart. Input must start with `curl `.
35+
36+
**Frontend state** (`frontend/src/App.tsx`): the UI is multi-tab ("Request 1", "Request 2", …). State is held as **parallel arrays indexed by tab**`reqBodies[]`, `reqHeaders[][]`, `responses[]` — all kept in sync in `addNewTab`/`closeTab`. When editing tab logic, update all three arrays together or they desync. Headers in the UI are `{Key, Value}` objects (`src/lib/header.ts`); they're converted to a plain `Record<string, string>` before being passed to Go (which expects `main.Headers`).
37+
38+
**UI stack**: the frontend uses **Tailwind CSS + shadcn/ui** (Radix primitives in `frontend/src/components/ui/`, `cn` helper in `src/lib/utils.ts`, design tokens as CSS variables in `src/index.css`, theme in `tailwind.config.js`). Icons are `lucide-react`. JSON responses are highlighted by the in-house `src/components/json-view.tsx` (no `react-json-pretty`). The `@/*` import alias maps to `src/`.
39+
40+
## Gotchas
41+
42+
- **Go module is named `changeme`** (`go.mod` placeholder, never renamed). Build works because Wails manages it; rename before publishing/importing.
43+
- **`frontend/hypr/` is a stale leftover** — a complete nested Wails scaffold (its own `go.mod`, `main.go`, `build/`, `frontend/`). It is **not** part of the real app (the real entry point is the root `main.go`). Don't edit files there expecting them to take effect.
44+
- **`frontend/wailsjs/` is generated**`App.d.ts`/`App.js`/`models.ts` are regenerated by Wails from the Go structs. Don't hand-edit; change the Go types and rebuild.

app_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
)
7+
8+
func TestHeadersToStr_SingleValue(t *testing.T) {
9+
h := http.Header{"Content-Type": []string{"application/json"}}
10+
if got := HeadersToStr(&h); got != "Content-Type: application/json" {
11+
t.Errorf("HeadersToStr() = %q, want %q", got, "Content-Type: application/json")
12+
}
13+
}
14+
15+
func TestHeadersToStr_MultipleValuesJoined(t *testing.T) {
16+
h := http.Header{"Set-Cookie": []string{"a=1", "b=2"}}
17+
if got := HeadersToStr(&h); got != "Set-Cookie: a=1; b=2" {
18+
t.Errorf("HeadersToStr() = %q, want %q", got, "Set-Cookie: a=1; b=2")
19+
}
20+
}
21+
22+
func TestHeadersToStr_Empty(t *testing.T) {
23+
h := http.Header{}
24+
if got := HeadersToStr(&h); got != "" {
25+
t.Errorf("HeadersToStr() = %q, want empty", got)
26+
}
27+
}

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8"/>
55
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
6-
<title>Hpyr</title>
6+
<title>Hypr</title>
77
</head>
88
<body>
99
<div id="root"></div>

0 commit comments

Comments
 (0)