Skip to content

MikeShorter/hello-not-sure

Repository files navigation

hello-not-sure

A small end-to-end Clojure project that exercises a fairly complete toolchain: a Ring/Reitit/Jetty server backed by SQLite on one side, a cljfx desktop client on the other, and a layered test suite plus static-analysis and build aliases glueing it together.

The name is an Idiocracy reference — if no one has ever introduced themselves to the server, it greets you as "Not Sure".

Project tree

hello-not-sure/
├── deps.edn                       # deps, aliases (server/client/test/lint/fmt/security/build)
├── build.clj                      # tools.build — two uberjars
├── tests.edn                      # Kaocha test-suite layout (unit / db / http)
├── .clj-kondo/config.edn          # linter config
├── .cljfmt.edn                    # formatter config
├── README.md
├── resources/
├── src/
│   └── hello_not_sure/
│       ├── common.clj             # pure helpers shared by server + client
│       ├── server/
│       │   ├── core.clj           # -main, CLI parsing
│       │   ├── system.clj         # lifecycle (datasource + Jetty)
│       │   ├── routes.clj         # Reitit routes + Malli schemas + Swagger
│       │   ├── handlers.clj       # request handlers
│       │   └── db.clj             # next.jdbc + HoneySQL
│       └── client/
│           ├── core.clj           # cljfx GUI
│           └── http.clj           # hato HTTP wrapper
└── test/
    └── hello_not_sure/
        ├── unit/common_test.clj   # pure-function unit tests
        ├── db/db_test.clj         # in-memory SQLite, per-test fixture
        └── http/http_test.clj     # Jetty on random port, per-test fixture

Architecture

Three layers, deliberately thin:

  1. Pure layer (hello-not-sure.common) — string normalization and the "Not Sure" default. No I/O. Cheap to test, reusable on both server and client.
  2. Persistence layer (hello-not-sure.server.db) — next.jdbc for the driver and HoneySQL for query construction. The datasource is a value passed in, so the same code runs against a file-backed SQLite in production and an in-memory SQLite in tests.
  3. Web layer (hello-not-sure.server.routes + handlers + system) — Reitit routes carry Malli schemas, which drive request/response coercion and the auto-generated OpenAPI document. Muuntaja handles JSON-in/JSON-out via Jsonista. Swagger UI is mounted at /swagger-ui. Jetty is started by system/start, which returns a value containing the server (for .stop) and the port (useful for tests on :port 0).

The client mirrors that split: client.http is a tiny hato wrapper that returns parsed maps, and client.core is the cljfx UI with a state atom and a defmulti event handler — no HTTP code in the view, no UI code in the HTTP layer.

Tests follow the same layering — one suite per layer in tests.edn, so you can run e.g. only the fast unit tests during a tight loop.

REST API

Method Path Body Response
POST /name {"name": "Joe"} 201 {"name": "Joe"}
GET /name 200 {"name": "<latest or Not Sure>"}
GET /swagger.json OpenAPI document
GET /swagger-ui Swagger UI

Running

# Start the server on http://localhost:3000 (db file: ./db.sqlite)
clj -M:server

# Start the cljfx client (talks to http://localhost:3000 by default)
clj -M:client
# …or point it at a different server:
clj -M:client http://localhost:8080

Open Swagger UI at http://localhost:3000/swagger-ui while the server is up.

Tests

Kaocha is configured with three independently-runnable suites:

clj -M:test                # run everything
clj -M:test --focus :unit  # only pure-function tests
clj -M:test --focus :db    # only database integration tests
clj -M:test --focus :http  # only HTTP integration tests
  • unit — no fixtures, no I/O.
  • dbuse-fixtures :each rebuilds the schema in an in-memory SQLite database per test, so tests can't leak state into each other.
  • httpuse-fixtures :each starts a fresh Jetty on :port 0 (random) backed by an in-memory SQLite for each test. The suite exercises the real Ring stack end-to-end with full per-test isolation.

Static analysis, coverage & dependency hygiene

clj -M:lint        # clj-kondo over src + test
clj -M:fmt         # cljfmt check
clj -M:fmt-fix     # cljfmt fix
clj -M:security    # clj-watson dependency vulnerability scan
clj -M:coverage    # cloverage HTML report -> target/coverage/index.html
clj -M:outdated    # antq report of newer dependency versions

Build

build.clj uses tools.build to produce two uberjars under target/.

clj -T:build clean
clj -T:build server-uber       # target/hello-not-sure-server-0.1.0.jar
clj -T:build client-uber       # target/hello-not-sure-client-0.1.0.jar
clj -T:build all               # clean + both uberjars

java -jar target/hello-not-sure-server-0.1.0.jar
java -jar target/hello-not-sure-client-0.1.0.jar

About

Small end-to-end Clojure project: Ring/Reitit/Jetty server + SQLite + cljfx client, with full toolchain demonstration

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors