TofuStack/README.md

93 lines
4.2 KiB
Markdown
Raw Normal View History

2024-05-27 18:26:23 +00:00
# Sveltekit - Taro Stack
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
## ❗ Important
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
If you forked this repository before May 27th, you'll want to view commit `653e2c2`. There was an issue with the Hono context
not correctly parsing routes.
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
## ❔ What
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
A scalable, testable, extensible, boilerplate for Sveltekit.
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
Sveltekit is awesome. File-based routing, SSG/SSR, and having the ability to have a backend attatched to your frontend saves incredible amounts of time and effort.
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
But the default backend sometimes isn't enough. There are some projects that require more powerful and feature rich backends. I'm talking Middleware, guards, pipes, interceptors, testing, event-emitters, task scheduling, route versioning, and so on.
So what I've done is attatched Hono, a fully fletched backend, to run on the Sveltekit process and forward all API requests to it.
2024-05-25 06:02:26 +00:00
2024-05-25 06:02:33 +00:00
`/api/[...slugs]`
2024-05-25 06:02:26 +00:00
2024-05-25 06:02:33 +00:00
```ts
import app from '$lib/api';
import type { RequestHandler } from '@sveltejs/kit';
2024-05-25 06:02:26 +00:00
2024-05-25 06:02:33 +00:00
export const GET: RequestHandler = ({ request }) => app.fetch(request);
export const PUT: RequestHandler = ({ request }) => app.fetch(request);
export const DELETE: RequestHandler = ({ request }) => app.fetch(request);
export const POST: RequestHandler = ({ request }) => app.fetch(request);
2024-05-25 06:02:26 +00:00
```
## Features
2024-05-27 18:26:23 +00:00
- 🟢 Full E2E typesafety
- 🟢 RPC Client for API Requests
- 🟢 Custom Fetch Wrapper
- 🔴 Deployment Template
- 🟠 Authentication
- 🟢 Email/Passkey
- 🔴 OAuth
- 🟢 Email Update/Verifiaction
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
## Technologies
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
- [Lucia](https://lucia-auth.com): Hits the right level of abstraction for me. Hand me the tools to build a secure authentication system and let me implement it to suite my needs
- [Drizzle](https://orm.drizzle.team/) - Drizzle advertises itself as an ORM but I think its deceptive. Its a query builder with a migration client. Everytime I've used an ORM, I find myself fighting it for sometimes the simplist of use cases. Drizzle just gives you type-safety while querying SQL in a native fashion. Learn SQL, not ORMs.
- [Hono](https://hono.dev/): Fast, lightweight, and built on web standards; meaning it can run anywhere you're Sveltekit app can. It's essentially a better, newer, and ironically more stable Express.JS. This provides us an extreemely good foundation to cleanly build ontop of without having to teardown first. It has a zod adapter for validating DTO's which can be shared with the frontend too.
- [Sveltekit](https://kit.svelte.dev/): After trying Vue, React, Next, and pretty much every frotnend framework in the JS ecosystem, its safe to say I vastly prefer Svelte and its priority of building on web standards.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
## Architecture
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
There are a few popular architectures for structuring backends. Technical, Onion, VSA, and the list goes on. I almost always choose
to start with Technical and let the project naturally evolve into one of the others.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
### Folder Structure
* **controllers** - Responsible for routing requests
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **services** - Responsible for handling business logic.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **repositories** - Responsible for retrieving and
storing data.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **infrastructure** - Handles the implementation of external services or backend operations.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **interfaces** - Common
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **middleware** - Middlware our request router is responsible for handling.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **providers** - Injectable services
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **dtos** - Data Transfer Objects (DTOs) are used to define the shape of data that is passed.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
* **common** - Anything commonly shared throughout the backend
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
### File Naming
You might notice how each file in the backend is postfixed with its architectural type(e.g. `iam.service.ts`). This allows
us to easily reorganize the folder structure to suite a different architecture.
2024-05-25 06:02:33 +00:00
2024-05-27 18:26:23 +00:00
For example, if you want to group folders by domain(DDD), you simply drag and drop all related files to that folder.
```
└── events/
├── events.controller.ts
├── events.service.ts
└── events.repository.ts
```
2024-05-25 06:02:33 +00:00
## Testing
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
Testing probably isn't first and foremost when creating an app. Thats fine. You shouldnt't be spending time writing tests if your app is changing and pivoting.
2024-05-25 06:02:26 +00:00
2024-05-27 18:26:23 +00:00
BUT a good stack should be **testable** when the time to solidify a codebase arrives. I created this stack with that pinciple in mind. I've provided a examples of how to write these tests under `authentication.service.test.ts` or `users.service.test.ts`