Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gold-windows-shine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@farbenmeer/router": minor
---

add switch component
5 changes: 5 additions & 0 deletions .changeset/sharp-suns-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@farbenmeer/tapi": patch
---

add explicit void response feature to TResponse api
5 changes: 5 additions & 0 deletions .changeset/silent-beans-pick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@farbenmeer/tapi": minor
---

patch, put, delete methods
40 changes: 40 additions & 0 deletions examples/todo-list/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store

# Bunny database file and build output
db.sqlite
.bunny

todos.sqlite
72 changes: 72 additions & 0 deletions examples/todo-list/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# @farbenmeer/bunny-boilerplate

## 0.2.2

### Patch Changes

- Updated dependencies [b4f73d8]
- @farbenmeer/bunny@0.3.0

## 0.2.1

### Patch Changes

- 3196826: add instructions for setting up tailwind
- @farbenmeer/bunny@0.2.4

## 0.2.0

### Minor Changes

- bb41e24: move to pnpm

### Patch Changes

- Updated dependencies [bb41e24]
- @farbenmeer/bunny@0.2.0

## 0.1.6

### Patch Changes

- 8620659: Bunny re-exports all the internal packages
- Updated dependencies [8620659]
- @farbenmeer/bunny@0.1.4

## 0.1.5

### Patch Changes

- Updated dependencies [c3e9eaa]
- @farbenmeer/bun-auth@0.1.3

## 0.1.4

### Patch Changes

- Updated dependencies [13eb226]
- @farbenmeer/bunny@0.1.3

## 0.1.3

### Patch Changes

- Updated dependencies [2578a14]
- Updated dependencies [3d47664]
- Updated dependencies [4140811]
- @farbenmeer/bunny@0.1.2
- @farbenmeer/bun-auth@0.1.2

## 0.1.2

### Patch Changes

- Updated dependencies [857aead]
- @farbenmeer/bunny@0.1.1

## 0.1.1

### Patch Changes

- Updated dependencies [ef420c7]
- @farbenmeer/bun-auth@0.1.1
23 changes: 23 additions & 0 deletions examples/todo-list/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# use the official Bun image
# see all versions at https://hub.docker.com/r/oven/bun/tags
FROM node:24-alpine AS base
WORKDIR /usr/src/app
ENV NODE_ENV=production

# install dependencies into temp directory
# this will cache them and speed up future builds
FROM base AS builder
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm run build --standalone

# copy production dependencies and source code into final image
FROM base AS runner
COPY --from=builder /usr/src/app/.bunny/prod .

# run the app
USER node
EXPOSE 3000/tcp
CMD [ "node", "server.js" ]
12 changes: 12 additions & 0 deletions examples/todo-list/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Bunny Project

This project was created using `@farbenmeer/bunny init`.

It uses the `@farbenmeer/bunny`-Framework.

Commands:
* `bun run dev` starts the dev-server.
* `bun run build` creates a production build.
* `bun run start` starts the production server (run `bun run build` first).
* `bun run generate` generates a migration based on the drizzle schema in `src/lib/schema.ts`
* `bun run migrate` to apply the migrations
32 changes: 32 additions & 0 deletions examples/todo-list/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@farbenmeer/bunny-boilerplate",
"version": "0.2.2",
"type": "module",
"private": true,
"files": [
"src",
".gitignore",
"Dockerfile",
"tsconfig.json"
],
"scripts": {
"dev": "bunny dev",
"build": "bunny build",
"start": "bunny start"
},
"dependencies": {
"@farbenmeer/bunny": "workspace:^",
"zod": "^4",
"react": "^19",
"react-dom": "^19"
},
"devDependencies": {
"@types/node": "^25.0.3",
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^4"
},
"peerDependencies": {
"typescript": "^5"
}
}
5 changes: 5 additions & 0 deletions examples/todo-list/src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineApi } from "@farbenmeer/bunny/server";

export const api = defineApi()
.route("/todos", import("./api/todos"))
.route("/todos/:id", import("./api/todo"));
38 changes: 38 additions & 0 deletions examples/todo-list/src/api/todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { defineHandler, TResponse } from "@farbenmeer/bunny/server";
import { db } from "db";
import z from "zod";

const params = {
id: z.string(),
};

export const DELETE = defineHandler(
{
params,
authorize: () => true,
},
async (req) => {
db.prepare("DELETE FROM todos WHERE id = ?").run(req.params().id);

return TResponse.void({ tags: ["todos"] });
}
);

export const PATCH = defineHandler(
{
params,
authorize: () => true,
body: z.object({
done: z.stringbool().optional(),
}),
},
async (req) => {
const { done } = await req.data();
db.prepare("UPDATE todos SET done = ? WHERE id = ?").run(
done ? 1 : 0,
req.params().id
);

return TResponse.void({ tags: ["todos"] });
}
);
33 changes: 33 additions & 0 deletions examples/todo-list/src/api/todos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { defineHandler, TResponse } from "@farbenmeer/bunny/server";
import { db } from "db";
import { z } from "zod";

const todo = z.object({
id: z.number(),
text: z.string(),
done: z.number().transform(Boolean),
});

export const GET = defineHandler(
{
authorize: () => true,
},
async () => {
const todos = todo.array().parse(db.prepare("SELECT * FROM todos").all());
return TResponse.json(todos, { tags: ["todos"] });
}
);

export const POST = defineHandler(
{
authorize: () => true,
body: z.object({
text: z.string().min(1),
}),
},
async (req) => {
const { text } = await req.data();
db.prepare("INSERT INTO todos (text, done) VALUES (?, ?)").run(text, 0);
return TResponse.void({ tags: ["todos"] });
}
);
37 changes: 37 additions & 0 deletions examples/todo-list/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useQuery } from "@farbenmeer/bunny/client";
import { client } from "client";

export function App() {
const todos = useQuery(client.todos.get());

return (
<div className="w-full h-screen flex flex-col items-center justify-center">
<h1 className="text-4xl font-bold">Bunny TODO List</h1>
<form action={client.todos.post}>
<input name="text" placeholder="Add a todo" />
<button type="submit">Add</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<form action={client.todos[todo.id]!.patch}>
<input
name="done"
type="checkbox"
defaultChecked={todo.done}
onChange={(e) => e.currentTarget.form?.requestSubmit()}
/>
</form>
{todo.text}
<form
className="delete-form"
action={client.todos[todo.id]!.delete}
>
<button type="submit">🗑</button>
</form>
</li>
))}
</ul>
</div>
);
}
4 changes: 4 additions & 0 deletions examples/todo-list/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createFetchClient } from "@farbenmeer/bunny/client";
import type { api } from "./api";

export const client = createFetchClient<typeof api.routes>("/api");
11 changes: 11 additions & 0 deletions examples/todo-list/src/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DatabaseSync } from "node:sqlite";

export const db = new DatabaseSync("todos.sqlite");

db.exec(`
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
text TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT 0
)
`);
14 changes: 14 additions & 0 deletions examples/todo-list/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/png" href="./logo.png" />
<link rel="stylesheet" href="./main.css" />
<title>Bunny</title>
<script type="module" src="./index.tsx" async></script>
</head>
<body>
<div id="__bunny"></div>
</body>
</html>
11 changes: 11 additions & 0 deletions examples/todo-list/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* This file is the entry point for the React app, it sets up the root
* element and renders the App component to the DOM.
*
* It is included in `src/index.html`.
*/

import { startBunnyClient } from "@farbenmeer/bunny/client";
import { App } from "app/app";

startBunnyClient(<App />);
26 changes: 26 additions & 0 deletions examples/todo-list/src/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
ul {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 24rem;
padding: 0;
}

li {
background-color: lightblue;
display: flex;
border-radius: 1rem;
padding: 1rem;
gap: 0.5rem;
align-items: center;
justify-content: start;
}

button {
background-color: white;
border: gray 1px solid;
}

.delete-form {
margin-left: auto;
}
4 changes: 4 additions & 0 deletions examples/todo-list/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "*.png" {
const value: string;
export default value;
}
Loading