Skip to content

Commit 6f79af6

Browse files
Layered Phase 6 - Misc (#174)
### Description <!-- Provide a comprehensive description here about what your PR aims to solve. --> <!-- You may also add additional context --> Misc refactor to Layered Architecture Closes #168 --- ### PR Checklist <!-- Please do not remove this section --> <!-- Mark each item with an "x" ([ ] becomes [x]) --> - [x] Read the Developer's Guide in [CONTRIBUTING.md](https://github.com/agnyz/bedstack/blob/main/CONTRIBUTING.md) - [x] Use a concise title to represent the changes introduced in this PR - [x] Provide a detailed description of the changes introduced in this PR, and, if necessary, some screenshots - [x] Reference an issue or discussion where the feature or changes have been previously discussed - [x] Add a failing test that passes with the changes introduced in this PR, or explain why it's not feasible - [x] Add documentation for the feature or changes introduced in this PR to the docs; you can run them with `bun docs` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced standardized error handling with a new `RealWorldError` class and structured error responses. - Added utility modules for error formatting, date operations, and validation tasks. - Added reusable interface types for API responses, pagination, and common entities. - Centralized and expanded constants for pagination and error messages. - **Refactor** - Unified and simplified error handling across services, replacing custom error classes with standardized errors and HTTP status codes. - Updated import paths throughout the codebase for consistency using a single alias pattern. - Reorganized and clarified project structure documentation and code organization. - Improved and centralized constants and utility exports for easier access. - **Bug Fixes** - Fixed broken Markdown links and standardized code block formatting in documentation. - **Chores** - Simplified TypeScript path aliases in configuration. - Cleaned up whitespace and improved formatting in all documentation files. - **Documentation** - Expanded and clarified project structure, usage guidelines, and added new documentation for utilities and interfaces. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 7903534 commit 6f79af6

File tree

113 files changed

+2168
-755
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+2168
-755
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- main
1414
paths-ignore:
1515
- 'docs/**'
16+
workflow_dispatch:
1617

1718
jobs:
1819
test-build:

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"password": "postgres"
1616
}
1717
],
18-
"cSpell.words": ["bedstack", "Elysia", "elysiajs", "favicons", "typesafe"]
18+
"cSpell.words": ["bedstack", "Elysia", "elysiajs", "favicons", "typesafe"],
19+
"typescript.tsdk": "node_modules/typescript/lib"
1920
}

CODE_OF_CONDUCT.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
1717
Examples of behavior that contributes to a positive environment for our
1818
community include:
1919

20-
* Demonstrating empathy and kindness toward other people
21-
* Being respectful of differing opinions, viewpoints, and experiences
22-
* Giving and gracefully accepting constructive feedback
23-
* Accepting responsibility and apologizing to those affected by our mistakes,
20+
- Demonstrating empathy and kindness toward other people
21+
- Being respectful of differing opinions, viewpoints, and experiences
22+
- Giving and gracefully accepting constructive feedback
23+
- Accepting responsibility and apologizing to those affected by our mistakes,
2424
and learning from the experience
25-
* Focusing on what is best not just for us as individuals, but for the
25+
- Focusing on what is best not just for us as individuals, but for the
2626
overall community
2727

2828
Examples of unacceptable behavior include:
2929

30-
* The use of sexualized language or imagery, and sexual attention or
30+
- The use of sexualized language or imagery, and sexual attention or
3131
advances of any kind
32-
* Trolling, insulting or derogatory comments, and personal or political attacks
33-
* Public or private harassment
34-
* Publishing others' private information, such as a physical or email
32+
- Trolling, insulting or derogatory comments, and personal or political attacks
33+
- Public or private harassment
34+
- Publishing others' private information, such as a physical or email
3535
address, without their explicit permission
36-
* Other conduct which could reasonably be considered inappropriate in a
36+
- Other conduct which could reasonably be considered inappropriate in a
3737
professional setting
3838

3939
## Enforcement Responsibilities
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
106106
### 4. Permanent Ban
107107

108108
**Community Impact**: Demonstrating a pattern of violation of community
109-
standards, including sustained inappropriate behavior, harassment of an
109+
standards, including sustained inappropriate behavior, harassment of an
110110
individual, or aggression toward or disparagement of classes of individuals.
111111

112112
**Consequence**: A permanent ban from any sort of public interaction within

CONTRIBUTING.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ Hey there! We're thrilled that you'd like to contribute to this project. Your he
99

1010
This project uses [Bun](https://bun.sh) as a runtime as well as a package manager. It's a modern, fast, and lightweight alternative to [Node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/). To install Bun on POSIX systems (like Ubuntu or macOS), run the following command:
1111

12-
```sh
13-
curl -fsSL https://bun.sh/install | bash
14-
```
12+
```sh
13+
curl -fsSL https://bun.sh/install | bash
14+
```
1515

1616
Otherwise, visit the [Bun installation page](https://bun.sh/docs/installation) for installation options.
1717

@@ -27,7 +27,7 @@ Build the project for production. The result is under `dist/`.
2727

2828
### `bun check`
2929

30-
We use [Biome](https://biomejs.dev/) for **both linting and formatting**. It is an ultra-fast, Rust based linter and formatter.
30+
We use [Biome](https://biomejs.dev/) for **both linting and formatting**. It is an ultra-fast, Rust based linter and formatter.
3131
It also lints JSON.
3232

3333
You can also run `bun fix` to apply any safe fixes automatically.
@@ -69,8 +69,9 @@ Where the template is:
6969
```
7070

7171
Replacing:
72-
* `<keyword>` with one of `close`, `closes`, `closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, `resolved`
73-
* `<issue-number>`: the issue number you are fixing
72+
73+
- `<keyword>` with one of `close`, `closes`, `closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, `resolved`
74+
- `<issue-number>`: the issue number you are fixing
7475

7576
This will let GitHub know the issues are linked, and automatically close them once the PR gets merged. Learn more at [the guide](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword).
7677

GOVERNANCE.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,31 @@
44

55
To understand the scope of this document, please read:
66

7-
* [*What is governance?* by Adobe](https://github.com/adobe/open-development-template/blob/master/Governance.md#meritocracy)
8-
* [*Jenkins Governance Document* for an inspiration](https://www.jenkins.io/project/governance/)
7+
- [_What is governance?_ by Adobe](https://github.com/adobe/open-development-template/blob/master/Governance.md#meritocracy)
8+
- [_Jenkins Governance Document_ for an inspiration](https://www.jenkins.io/project/governance/)
99

1010
## Who we are
1111

1212
We are a group of open-source developers who develop, use, promote the Elysia RealWorld example app, software around it, and other related activities for our mutual benefit.
1313

1414
## Core Philosophy
1515

16-
* **Lower barrier to entry**
16+
- **Lower barrier to entry**
1717

18-
Everyone is welcome to contribute, regardless of their background, experience, or identity. We value all contributions, and we are committed to providing a friendly, safe, and welcoming environment for all. Everyone gets a voice, and everyone is listened to.
18+
Everyone is welcome to contribute, regardless of their background, experience, or identity. We value all contributions, and we are committed to providing a friendly, safe, and welcoming environment for all. Everyone gets a voice, and everyone is listened to.
1919

20-
* **Seeking consensus**
20+
- **Seeking consensus**
2121

22-
We seek consensus among contributors, and we are open to new ideas and approaches. When consensus cannot be reached after giving the stage to all parties, we will use a majority-wins voting process. We will strive to resolve conflicts in a constructive manner.
22+
We seek consensus among contributors, and we are open to new ideas and approaches. When consensus cannot be reached after giving the stage to all parties, we will use a majority-wins voting process. We will strive to resolve conflicts in a constructive manner.
2323

24-
* **Meritocracy**
24+
- **Meritocracy**
2525

26-
We value contributions based on their technical merit, and we welcome new contributors based on their demonstrated ability to contribute. Valuable contributers will be granted access to private channels and will be able to participate in the decision-making process.
27-
28-
* **Transparency**
29-
30-
While the decision-making process is not always public, the results of the decision making process must be public. Decisions will be made after thoughtful consideration of the community's input through [Discord](https://discord.gg/8UcP9QB5AV) and [GitHub Discussions](https://github.com/agnyz/bedstack/discussions).
26+
We value contributions based on their technical merit, and we welcome new contributors based on their demonstrated ability to contribute. Valuable contributers will be granted access to private channels and will be able to participate in the decision-making process.
3127

32-
* **Automation**
28+
- **Transparency**
3329

34-
We rely on automation to make our processes more efficient and to reduce the burden on contributors. We will automate as much as possible, and we will strive to make our automation tools accessible to all contributors. The goal is to abstract away the mundane tasks and let contributors focus on the fun stuff.
30+
While the decision-making process is not always public, the results of the decision making process must be public. Decisions will be made after thoughtful consideration of the community's input through [Discord](https://discord.gg/8UcP9QB5AV) and [GitHub Discussions](https://github.com/agnyz/bedstack/discussions).
31+
32+
- **Automation**
33+
34+
We rely on automation to make our processes more efficient and to reduce the burden on contributors. We will automate as much as possible, and we will strive to make our automation tools accessible to all contributors. The goal is to abstract away the mundane tasks and let contributors focus on the fun stuff.

PROJECT_STRUCTURE.md

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,91 @@ We follow a **one file per thing** rule to maintain clear organization.
88

99
```plaintext
1010
src/
11-
├── app.ts # Initializes and mounts the app
12-
├── routes/ # Aggregates and mounts feature routers
13-
├── db/ # Drizzle ORM config and database init
14-
├── shared/ # Common utilities and helpers
15-
├── articles/ # Full article feature module
16-
├── comments/ # Full comment feature module
17-
├── tags/ # Tag-related logic and schema
18-
├── users/ # User logic (repo, profile dto)
11+
├── app.module.ts # Main module that composes all features
12+
├── database.providers.ts # Database providers
13+
├── main.ts # Entry point
14+
├── ...resources/ # All resource modules directly under `src/`
15+
├── common/ # Common constants, interfaces, and utilities\
16+
scripts/ # Scripts managed by `package.json`
17+
drizzle/ # Drizzle migrations and scripts
18+
drizzle.config.ts # Drizzle configuration
19+
biome.json # Biome configuration
20+
package.json # Package metadata
21+
bun.lockb # Bun lockfile
22+
tsconfig.json # TypeScript configuration
23+
...markdown files # Documentation
24+
...git files # `.git/`, `.gitignore`, etc.
25+
...docker files # `docker-compose.yml`, `Dockerfile`, etc.
26+
.env* # `.env`, `.env.example`, etc.
27+
env.config.ts # Environment variables configuration
1928
```
2029

21-
## Feature Folder Layout
30+
> [!NOTE]
31+
> The `app.module.ts` file is named in the spirit of NestJS, where the app module is the device in charge of putting together all the pieces of the application. See [NestJS Modules](https://docs.nestjs.com/modules) for more details.
2232
23-
Each feature (e.g. `articles/`, `comments/`) uses this layout:
33+
## Folders Inside `src/`
34+
35+
### Resource Modules (`articles/`, `comments/`, etc.)
36+
37+
Each resource module uses this layout:
2438

2539
```plaintext
26-
feature/
27-
├── feature.controller.ts # REST handler logic
28-
├── feature.service.ts # Business logic
29-
├── feature.repository.ts # DB access logic
30-
├── feature.mapper.ts # Converts DB to DTO
40+
resource/
41+
├── resources.controller.ts # REST handler logic
42+
├── resources.service.ts # Business logic
43+
├── resources.repository.ts # DB access logic
44+
├── resources.mapper.ts # Converts DB to DTO
3145
├── schema/
32-
│ └── feature.schema.ts # Drizzle schema + optional relations
46+
│ └── resource.schema.ts # Drizzle schema + optional relations
3347
├── dto/
34-
│ ├── create-feature.dto.ts # Input shape (TypeBox)
35-
│ ├── update-feature.dto.ts # Input shape (if needed)
36-
│ └── feature.dto.ts # Output DTO for response
48+
│ ├── create-resource.dto.ts # Input shape (TypeBox)
49+
│ ├── update-resource.dto.ts # Input shape (if needed)
50+
│ └── resource.dto.ts # Output DTO for response
3751
├── interfaces/
38-
│ ├── feature.interface.ts # Domain model
39-
│ └── feature-row.interface.ts# Drizzle-inferred DB shape
52+
│ ├── resource.interface.ts # Domain model
53+
│ └── resource-row.interface.ts# Drizzle-inferred DB shape
4054
```
4155

42-
## Folder-Level Purpose
56+
> [!NOTE]
57+
> Note the filename is written in plural form (`resources.controller.ts`, e.g. `articles.controller.ts`) in the spirit of NestJS.
58+
59+
### Other Folders Inside `src/`
4360

44-
### `/db/`
61+
#### `database/`
4562

46-
- Drizzle config and init
47-
- Exports the db instance
63+
- Exports the db instance through `database.providers.ts`
4864
- Does **not** export db tables, these are found as schemas inside feature folders
65+
- Does **not** export Drizzle config and migrations, these are found in `drizzle.config.ts` and `drizzle/` (from the root of the project) respectively
4966

50-
### `/shared/`
67+
#### `common/`
5168

52-
Global utilities, middleware, and shared concerns.
69+
Global utilities, middleware, and common concerns.
5370

5471
```plaintext
55-
shared/
56-
├── auth-middleware.ts # Extracts auth context
57-
├── http-errors.ts # Shared error classes
58-
├── slugify.ts # Utility for slug generation
72+
common/
73+
├── constants/ # All global constants, grouped by domain
74+
│ ├── auth.constants.ts
75+
│ ├── validation.constants.ts
76+
│ └── realworld.constants.ts
77+
├── errors/ # Global error types and helpers
78+
│ ├── realworld.error.ts # RealWorld API-compliant base error class
79+
│ └── error.factory.ts # Helpers for throwing structured errors
80+
├── interfaces/ # Global interfaces (not feature-specific)
81+
│ └── pagination.interface.ts
82+
├── utils/ # Pure utility functions used app-wide
83+
│ ├── slugify.ts
84+
│ └── date.utils.ts
5985
```
6086

87+
> [!NOTE]
88+
> The `common/` folder is a catch-all for things that are not specific to a single feature. It's organized by purpose, not by type/domain. That's why it can have both `errors/` (domain) and `utils/` (type) folders.
89+
90+
> [!WARNING]
91+
> Avoid dumping everything into `common/` by default. If a util, constant, or interface is only used in one feature - keep it inside that feature's folder. Promote it to `common/` only when it's reused.
92+
93+
> [!TIP]
94+
> Only one `constants/` folder exists across the project - do not spread constants into individual features unless strictly private to that feature.
95+
6196
## Naming Conventions
6297

6398
### DTO Naming
@@ -80,7 +115,7 @@ shared/
80115
- May also define `relations()` in the same file unless very large
81116
- If split, name the second file `feature-relations.schema.ts`
82117

83-
## See also
118+
## See Also
84119

85120
- More on **Architecture** - see [Architecture](ARCHITECTURE.md)
86121
- **Contributing** - see [Developer's Guide](CONTRIBUTING.md)

README.md

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,53 @@
77

88
[RealWorld](https://realworld-docs.netlify.app/) example app for [Bun](https://bun.sh/) + [ElysiaJS](https://elysiajs.com/) + [Drizzle](https://orm.drizzle.team/)
99

10-
[![Tests Status](https://github.com/agnyz/bedstack/actions/workflows/tests.yml/badge.svg?event=push&branch=main)](https://github.com/agnyz/bedstack/actions/workflows/tests.yml?query=branch%3Amain) [![Fully compliant with the RealWorld API spec](https://img.shields.io/badge/RealWorld%20API-compatible-success?labelColor=2f1c42)](https://realworld-docs.netlify.app/specifications/backend/endpoints) [![Featured on CodebaseShow](https://img.shields.io/badge/CodebaseShow-approved-success?labelColor=2c3669)](https://codebase.show/projects/realworld?category=backend&language=typescript) [![GitHub License](https://img.shields.io/github/license/agnyz/bedstack)](https://github.com/agnyz/bedstack/blob/main/LICENSE) [![Star bedstack on GitHub](https://img.shields.io/github/stars/agnyz/bedstack)](https://github.com/agnyz/bedstack)
10+
[![Tests Status](https://github.com/agnyz/bedstack/actions/workflows/tests.yml/badge.svg?event=push&branch=main)](https://github.com/agnyz/bedstack/actions/workflows/tests.yml?query=branch%3Amain) [![Fully compliant with the RealWorld API spec](https://img.shields.io/badge/RealWorld%20API-compatible-success?labelColor=2f1c42)](https://realworld-docs.netlify.app/specifications/backend/endpoints) [![Featured on CodebaseShow](https://img.shields.io/badge/CodebaseShow-approved-success?labelColor=2c3669)](https://codebase.show/projects/realworld?category=backend&language=typescript) [![GitHub License](https://img.shields.io/github/license/agnyz/bedstack)](https://github.com/agnyz/bedstack/blob/main/LICENSE) [![Star bedstack on GitHub](https://img.shields.io/github/stars/agnyz/bedstack)](https://github.com/agnyz/bedstack)
1111

12-
## Let's share a BED - join our [Discord server](https://discord.gg/8UcP9QB5AV)
12+
## Let's share a BED - join our [Discord server](https://discord.gg/8UcP9QB5AV)
1313

1414
</div>
1515

1616
### Quickstart
1717

1818
1. **Clone and install dependencies**
1919

20-
```sh
21-
gh repo clone agnyz/bedstack
22-
cd bedstack
23-
bun i
24-
```
20+
```sh
21+
gh repo clone agnyz/bedstack
22+
cd bedstack
23+
bun i
24+
```
2525

2626
2. **Create a `.env` file**
2727

28-
```sh
29-
cp .env.example .env
30-
```
28+
```sh
29+
cp .env.example .env
30+
```
3131

32-
Use the provided example values or replace them with your own.
32+
Use the provided example values or replace them with your own.
3333

3434
3. **Ensure Docker daemon is running and spin up the Postgres container**
3535

36-
```sh
37-
bun db
38-
```
39-
3. **Migrate the schema to the database**
36+
```sh
37+
bun db
38+
```
4039

41-
```sh
42-
bun db:migrate
43-
```
40+
4. **Migrate the schema to the database**
4441

45-
4. **Run the development server**
42+
```sh
43+
bun db:migrate
44+
```
4645

47-
```sh
48-
bun dev
49-
```
46+
5. **Run the development server**
5047

51-
5. **Run the API tests**
48+
```sh
49+
bun dev
50+
```
5251

53-
```sh
54-
bun run test # not `bun test`!
55-
```
52+
6. **Run the API tests**
53+
54+
```sh
55+
bun run test # not `bun test`!
56+
```
5657

5758
### Building for production
5859

@@ -61,15 +62,15 @@
6162
6263
1. **Build the app**
6364

64-
```sh
65-
bun run build # not `bun build`!
66-
```
65+
```sh
66+
bun run build # not `bun build`!
67+
```
6768

6869
2. **Run the server**
6970

70-
```sh
71-
bun preview
72-
```
71+
```sh
72+
bun preview
73+
```
7374

7475
### Contributing
7576

0 commit comments

Comments
 (0)