AdelieStack/README.md

119 lines
5.9 KiB
Markdown
Raw Permalink Normal View History

# Sveltekit - Adelie Stack
2024-12-31 22:43:09 +00:00
This stack is a cloned and modified version of GitHub user [Rykuno](https://github.com/rykuno)'s [TofeStack](https://github.com/Rykuno/TofuStack).
2024-12-31 22:43:09 +00:00
## ❔ What
A scalable, testable, extensible, template for Sveltekit.
Sveltekit is awesome, but sometimes you need a bit more capability in the backend than what frameworks like
NextJS & Sveltekit can deliver.
To remedy this, I've attached a fully fleshed out backend to run on the Sveltekit process and forward all API requests
to it and paired it with some architectural patterns.
2024-12-31 22:43:09 +00:00
`/api/[...slugs]`
```ts
import app from '$lib/api';
import type { RequestHandler } from '@sveltejs/kit';
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);
export const fallback: RequestHandler = ({ request }) => app.fetch(request);
2024-12-31 22:43:09 +00:00
```
## Local Setup
1. Make sure Docker is running
2. Copy the `.env.example` file and rename to `.env`
3. Ensure that DB_SEEDING and DB_MIGRATING are set to `true` in the `.env` for this first run.
4. `pnpm install`
5. The database extension `citext` is being used to allow for case-insensitive string matching. To install the extension run `CREATE EXTENSION IF NOT EXISTS citext;` or add inside an additional drizzle SQL file for startup to use.
6. `pnpm initialize` (this will start the docker-compose and run the initial database migration.)
7. `pnpm dev`
8. Ensure that DB_SEEDING and DB_MIGRATING are set back to `false` in the `.env` after initial set up.
2024-12-31 22:43:09 +00:00
No additional setup is required, zero api keys, zero services to signup for, zero cost.
## How to Use
This is **not** supposed to serve as an all batteries included ["production boilerplate"](https://github.com/ixartz/Next-js-Boilerplate) with 200 useless sponsored features that get in your way.
Templates that do this are ANYTHING but "production" and "quick start".
2024-12-31 22:43:09 +00:00
This is stack is designed to be library agnostic. The philosophy here is to boostrap the concrete, repetitive,
and time-consuming tasks that every application will need regardless of what you're building.
2024-12-31 22:43:09 +00:00
**So - fork this repo, add your favorite libraries, and build out your own "more opinionated" personal template tailored to you**!
## Features
- 🟢 Full E2E typesafety
- 🟢 RPC Client for API Requests
- 🟢 Custom Fetch Wrapper
- 🟢 Deployment Template
- 🟠 Authentication
- 🟢 Email / Passkey
- 🟢 Username / Email and Password
2024-12-31 22:43:09 +00:00
- 🔴 OAuth
- 🟢 Email Update / Verification
2024-12-31 22:43:09 +00:00
- 🟢 Rate limiter
## Technologies
I'm mostly un-opinionated of what technology or libraries someone uses. Wanna [uwu'ify](https://www.npmjs.com/package/owoifyx) your entire app? Go for it.
2024-12-31 22:43:09 +00:00
That being said, there are some libraries that embody my philosophies of building software more than others,
2024-12-31 22:43:09 +00:00
- [Oslo-project](https://oslojs.dev/): Used for implementing crypto, encoding, hashing, and more in the authentication layer.
- [ArcticJS](https://arcticjs.dev/): Arctic is a collection of OAuth 2.0 clients for popular providers. It only supports the authorization code grant type and intended to be used server-side.
- [Drizzle](https://orm.drizzle.team/) - Drizzle advertises itself as an ORM, but I think its deceptive. It's a query builder with a migration client. Everytime I've used an ORM, I find myself fighting it for sometimes the simplest 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 a perfect foundation to cleanly build on top 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://svelte.dev/docs/kit/introduction): After trying Vue, React, Next, and pretty much every frontend framework in the JS ecosystem, it's safe to say I vastly prefer Svelte and its priority of building on **web standards**.
2024-12-31 22:43:09 +00:00
## Architecture
There are a few popular architectures for structuring backends. Technical, Onion, DDD, 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 as complexity grows.
### Backend Folder Structure
- **controllers** - Responsible for routing requests
- **services** - Responsible for handling business logic.
- **repositories** - Responsible for retrieving and
storing data.
- **infrastructure** - Handles the implementation of external services or backend operations.
- **middleware** - Middlware our request router is responsible for handling.
- **providers** - Injectable services
- **dtos** - Data Transfer Objects (DTOs) are used to define the shape of data that is passed.
- **common** - Anything commonly shared throughout the backend
### 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 pattern if the domain becomes more complex.
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
```
## Testing
Testing probably isn't first and foremost when creating an app. That's fine. You should not be spending time writing tests if your app is mutable.
2024-12-31 22:43:09 +00:00
BUT, a good stack should be **testable** when the time to solidify a codebase arrives. I created this stack with that principle in mind. I've provided a examples of how to write these tests under `authentication.service.test.ts` or `users.service.test.ts`