1 parent
cc7466823b
commit
e8c5b414d9
44 files changed
+7649
-344
No files matched your search
+58
-27
@@ -1,32 +1,63 @@
|
||||
# React + TypeScript + Vite
|
||||
# The console
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
|
||||
Vite + React + TypeScript + Tailwind, built into `internal/web/dist` and served
|
||||
by the Go binary from an `//go:embed`. There is no separate deployment: the
|
||||
binary *is* the console.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
## Day-to-day
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
||||
|
||||
## React Compiler
|
||||
|
||||
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
||||
|
||||
## Expanding the Oxlint configuration
|
||||
|
||||
If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["react", "typescript", "oxc"],
|
||||
"options": {
|
||||
"typeAware": true
|
||||
},
|
||||
"rules": {
|
||||
"react/rules-of-hooks": "error",
|
||||
"react/only-export-components": ["warn", { "allowConstantExport": true }]
|
||||
}
|
||||
}
|
||||
```sh
|
||||
make web-check # npx tsc -b --noEmit && npm run build (what CI runs)
|
||||
make web-dev # Vite dev server, proxying /api to 127.0.0.1:8080
|
||||
make web # production build into internal/web/dist
|
||||
```
|
||||
|
||||
See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories.
|
||||
For `make web-dev` to show anything, a `fancy-dns` has to be listening on
|
||||
127.0.0.1:8080 with the API key the console sends. `deploy/config.example.yaml`
|
||||
binds there, but on port 53; rewrite the ports (or use `make smoke`, which does
|
||||
it for you) before starting it.
|
||||
|
||||
Two traps that have cost time, both from `AGENTS.md`:
|
||||
|
||||
- **`tsc -b` replays cached diagnostics** from `node_modules/.tmp/*.tsbuildinfo`.
|
||||
After a large edit `rm -f node_modules/.tmp/*.tsbuildinfo`, or you will read
|
||||
errors that no longer exist and miss ones that do.
|
||||
- **`npm run build` empties `internal/web/dist` and deletes its `.gitkeep`.**
|
||||
Restore it (`git checkout -- internal/web/dist/.gitkeep`). The Go build still
|
||||
works while the directory is empty, so a console rebuild in the middle of
|
||||
someone else's `go build` is not fatal — but the commit is.
|
||||
|
||||
## The API contract
|
||||
|
||||
`src/lib/types.ts` is a **hand-written mirror** of the Go `json` tags in
|
||||
`internal/api` and `internal/app/hooks.go`. `apiFetch` ends in
|
||||
`JSON.parse(text) as T`, so the compiler checks the console against its own
|
||||
declarations and nothing else: a field that loses its `json` tag, or a response
|
||||
a struct never had, shows up as an empty table in a browser and nowhere else.
|
||||
That is not hypothetical — a round of this found the Sources table, the ACL
|
||||
group cards and both Save buttons broken exactly that way.
|
||||
|
||||
So, when you touch either side:
|
||||
|
||||
- **Go**: add or keep the `json` tag. `internal/app` has contract tests that
|
||||
assert the exact key set of every admin endpoint; they are the spec, and a
|
||||
rename fails them.
|
||||
- **Console**: change the interface in the same commit. If the server is wrong,
|
||||
fix the server — do not "adapt" in the client, and do not paper a mismatch
|
||||
over with `as any`, an optional field or a `?? 0` default. Those casts are
|
||||
precisely what hides drift.
|
||||
- Never rename a field on one side only. The dashboard, the ServiceMonitor
|
||||
queries and the Grafana panels are consumers of the same JSON.
|
||||
|
||||
The durable fix is to generate `types.ts` from the Go structs, or to publish an
|
||||
OpenAPI document from the server and generate from that. It is in the plan at
|
||||
the end of `STATUS.md`.
|
||||
|
||||
## What is checked
|
||||
|
||||
`npx tsc -b --noEmit` (strict, with `noUnusedLocals`) and `oxlint` (two rules:
|
||||
`react/rules-of-hooks` and `react/only-export-components`). There is **no test
|
||||
runner** and no component test — the console's correctness rests entirely on its
|
||||
types, which are only as good as the mirror above. Adding vitest and a handful
|
||||
of tests for `lib/format.ts` (the percent/latency/duration formatters, which
|
||||
have already shipped a units bug) is cheap and worth doing.
|
||||
Reference in new issue
Block a user