├── .env.example ├── .gitignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── bun.lockb ├── package.json ├── prisma └── schema.prisma ├── src ├── db │ └── index.ts ├── index.ts └── resources │ └── users │ ├── router.ts │ └── service.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # env files 28 | .env* 29 | !.env.example 30 | 31 | # vercel 32 | .vercel 33 | 34 | **/*.trace 35 | **/*.zip 36 | **/*.tar.gz 37 | **/*.tgz 38 | **/*.log 39 | package-lock.json 40 | **/*.bun 41 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "bracketSpacing": true, 4 | "tabWidth": 2, 5 | "semi": true, 6 | "singleQuote": true, 7 | "arrowParens": "always" 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Elysia Starter

3 |

A batteries included API started built with ElysiaJS.

4 | Deploy on Railway 5 |
6 | 7 | ## 🔋 Batteries Included 8 | 9 | - 🥟 [Bun](https://bun.sh/) 10 | - 👮 [TypeScript](https://www.typescriptlang.org/) 11 | - 🦊 [ElysiaJS](https://elysiajs.com/) 12 | - 🧰 [Prisma](https://prisma.io/) 13 | - 🐘 [Postrges](https://www.postgresql.org/) 14 | - 🚄 One-click [Railway](https://railway.app/) deploys 15 | 16 | ## 🚀 Getting Started 17 | 18 | To get started with this template, ensure that [Bun](https://bun.sh/) is installed. 19 | 20 | ```bash 21 | curl -fsSL https://bun.sh/install | bash 22 | ``` 23 | 24 | ### Development 25 | 26 | 1. Install dependencies 27 | 28 | ```bash 29 | bun install 30 | ``` 31 | 32 | 1. Start the development server 33 | 34 | ```bash 35 | bun run dev 36 | ``` 37 | 38 | Open http://localhost:3000/ with your browser to see the result. 39 | 40 | ## 🏛️ Architecture and Design 41 | 42 | #### TypeIDs 43 | 44 | This starter uses [TypeIDs](https://github.com/jetpack-io/typeid-js) which are type-safe, K-sortable, unique identifiers inspired by Stripe IDs. An example ID for a user would be `user_123456`. 45 | 46 | ### API Resources 47 | 48 | Each API resource (eg. `users`) are defined in `src/resources`. Each resource has a `router.ts` and `service.ts`. All the endpoints for the resource are defined in `router.ts` and all of the business logic ends up in `service.ts`. 49 | 50 | ## 🗺️ Roadmap 51 | 52 | - [ ] JWT authentication 53 | - [ ] Sane HTTP server defaults (CORS, etc.) 54 | - [ ] Better interop between Prisma and typebox 55 | - [ ] Example tests 56 | - [ ] Docker support 57 | - [ ] Monorepo with Next.js 58 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amorriscode/elysia-starter/7ab9fe706ba45c0ef090515250a1ebcedfdaded7/bun.lockb -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elysia-starter", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "test": "echo \"Error: no test specified\" && exit 1", 6 | "dev": "bun run --watch src/index.ts", 7 | "build": "bun build --target=bun ./src/index.ts --outdir ./build", 8 | "db:generate": "prisma generate", 9 | "db:migrate": "prisma migrate dev", 10 | "db:studio": "prisma studio" 11 | }, 12 | "dependencies": { 13 | "@prisma/client": "^5.3.1", 14 | "@sinclair/typebox": "^0.31.17", 15 | "elysia": "latest", 16 | "prisma": "^5.3.1", 17 | "typeid-js": "^0.3.0" 18 | }, 19 | "devDependencies": { 20 | "bun-types": "latest", 21 | "prettier": "^3.0.3", 22 | "prisma-typebox-generator": "^2.1.0" 23 | }, 24 | "module": "src/index.js" 25 | } 26 | -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x"] 7 | } 8 | 9 | datasource db { 10 | provider = "postgresql" 11 | url = env("DATABASE_URL") 12 | } 13 | 14 | model User { 15 | id String @id 16 | email String @unique 17 | name String? 18 | } 19 | -------------------------------------------------------------------------------- /src/db/index.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | 3 | export const prisma = new PrismaClient(); 4 | export * from '@prisma/client'; 5 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Elysia } from 'elysia'; 2 | import { users } from '~/resources/users/router'; 3 | 4 | const app = new Elysia() 5 | .get('/', () => 'Eat your vegetables 🥦') 6 | .use(users) 7 | .listen(process.env.PORT ?? 3000); 8 | 9 | console.log( 10 | `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}` 11 | ); 12 | -------------------------------------------------------------------------------- /src/resources/users/router.ts: -------------------------------------------------------------------------------- 1 | import { Elysia } from 'elysia'; 2 | import { getUser, createUser, UserInput } from './service'; 3 | 4 | export const users = new Elysia({ prefix: '/users' }) 5 | .get('/:userId', ({ params: { userId } }) => getUser(userId)) 6 | .post('/', ({ body }) => createUser(body), { 7 | body: UserInput, 8 | }); 9 | -------------------------------------------------------------------------------- /src/resources/users/service.ts: -------------------------------------------------------------------------------- 1 | import { t, NotFoundError } from 'elysia'; 2 | import { Static } from '@sinclair/typebox'; 3 | import { typeid } from 'typeid-js'; 4 | import { prisma } from '~/db'; 5 | 6 | export const UserInput = t.Object({ 7 | email: t.String(), 8 | name: t.Optional(t.String()), 9 | }); 10 | type UserInputType = Static; 11 | 12 | export async function getUser(id: string) { 13 | try { 14 | const user = await prisma.user.findUnique({ 15 | where: { id }, 16 | }); 17 | 18 | if (!user) { 19 | throw new NotFoundError('User not found'); 20 | } 21 | 22 | return user; 23 | } catch (error) { 24 | console.error('Error finding user:', error); 25 | } 26 | } 27 | 28 | export async function createUser(args: UserInputType) { 29 | return prisma.user.create({ 30 | data: { 31 | id: typeid('user').toString(), 32 | ...args, 33 | }, 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2021", 4 | "module": "ES2022", 5 | "moduleResolution": "node", 6 | "baseUrl": ".", 7 | "paths": { 8 | "~/*": ["src/*"] 9 | }, 10 | "types": ["bun-types"], 11 | "esModuleInterop": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "strict": true, 14 | "skipLibCheck": true 15 | } 16 | } 17 | --------------------------------------------------------------------------------