You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DB layer (src/bin/api/db/):
- native.rs: NativeRepository (tokio-rusqlite) implementing all CRUD ops,
dynamic WHERE for filters, two-phase auth check for update, 13 unit tests
- d1.rs: D1Repository wasm32 stub (all methods return Internal error)
- connection.rs: open() helper — WAL + foreign_keys pragmas
- mod.rs: cfg-gate async_trait (Send on native, ?Send on wasm32)
Handlers (src/bin/api/handlers/mod.rs):
- All 7 routes: GET /api/, random, {id}, list, PUT create, POST update, DELETE
- Router order: random BEFORE {id} (prevents "random" matching as id)
- Auth: X-Auth-Code header validation → 403 on mismatch
- 13 handler unit tests with MockRepo
main.rs: opens DB, runs migrations, wraps in Arc<dyn Repo + Send + Sync>,
binds on $PORT (default 3000)
Cargo.toml: tower dev-dep for ServiceExt::oneshot in tests
All 32 tests pass (26 api + 6 lib)
Tickets closed: 00aff0 a5049d 6e829e 28e7d9 886bfd 2ce22e 5dbb7d 05f8ae
d792e2 5d9f5a b20b5a 175382 03bb91
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
3 months ago | |
|---|---|---|
| .. | ||
| .gitignore | 3 months ago | |
| README.md | 3 months ago | |
| d1.tf | 3 months ago | |
| dns.tf | 3 months ago | |
| main.tf | 3 months ago | |
| pages.tf | 3 months ago | |
| providers.tf | 3 months ago | |
| schema.sql | 3 months ago | |
| variables.tf | 3 months ago | |
| worker.tf | 3 months ago | |
README.md
quotesdb Infrastructure
OpenTofu configuration for deploying quotesdb to Cloudflare.
Resources provisioned
| Resource | Description |
|---|---|
cloudflare_d1_database.quotesdb |
D1 SQLite database backing the API |
cloudflare_workers_script.api |
Compiled Wasm Worker serving /api/* |
cloudflare_worker_route.api |
Routes quotes.elijah.run/api/* to the Worker |
cloudflare_pages_project.ui |
Pages project hosting the Yew SPA |
cloudflare_record.ui |
CNAME quotes.elijah.run → Pages |
cloudflare_pages_domain.ui |
Custom domain binding on Pages |
Required credentials
| Variable | Description |
|---|---|
TF_VAR_cloudflare_api_token |
Cloudflare API token (Workers, D1, Pages, DNS edit) |
TF_VAR_cloudflare_account_id |
Cloudflare account ID |
TF_VAR_cloudflare_zone_id |
Zone ID for elijah.run |
Export these before running tofu:
export TF_VAR_cloudflare_api_token="..."
export TF_VAR_cloudflare_account_id="..."
export TF_VAR_cloudflare_zone_id="..."
First-time setup (chicken-and-egg)
D1 must exist before the Worker can bind to it. On the very first deploy:
cd infra/
tofu init
tofu apply -target=cloudflare_d1_database.quotesdb
wrangler d1 execute quotesdb --file schema.sql --remote
tofu apply
Subsequent deploys: CI/CD handles everything automatically.
Local apply
cd quotesdb/infra/
tofu init
tofu plan
tofu apply
State
State is stored locally in terraform.tfstate (gitignored). For a team setup, migrate to a remote backend (S3-compatible bucket, Terraform Cloud, etc.).
Files
| File | Purpose |
|---|---|
main.tf |
Terraform block and provider version constraints |
providers.tf |
Cloudflare provider configuration |
variables.tf |
Input variable declarations |
d1.tf |
Cloudflare D1 database resource |
worker.tf |
Cloudflare Workers script + route |
pages.tf |
Cloudflare Pages project |
dns.tf |
DNS record and custom domain binding |
schema.sql |
Idempotent D1 schema (applied via wrangler, not tofu) |
.gitignore |
Ignores state, lock, and credential files |