Documentation Index
Fetch the complete documentation index at: https://www.orionjs.com/llms.txt
Use this file to discover all available pages before exploring further.
An Orionjs application follows a modular, component-based architecture that promotes clean organization and separation of concerns.
Root Directory
/
├── app/ # Main application code
├── node_modules/ # Project dependencies
├── .env.local.yml # Environment variables for local development
├── .gitignore # Git ignore file
├── biome.json # Biome configuration (for linting/formatting)
├── package.json # Project dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── bun.lock # Bun dependency lock file
App Directory
The app directory contains all the application code:
app/
├── config/ # Application configuration
├── components/ # Application components
├── env.d.ts # Environment file created by @orion-js/env
└── index.ts # Application entry point
Component Structure
Each component follows a consistent structure:
exampleComponent/
├── controllers/ # Controllers for different aspects of the component
│ ├── echoes/ # Event listeners
│ ├── routes/ # HTTP routes
│ ├── jobs/ # Background jobs
│ ├── modelResolvers/ # GraphQL model resolvers
│ └── resolvers/ # GraphQL resolvers container folder
│ ├── users/ # User-related resolvers
│ ├── orders/ # Order-related resolvers
│ └── products/ # Product-related resolvers
│ └── index.ts # Exports all the resolvers in all subfolders as a single array
├── repos/ # Data repositories
├── schemas/ # Data schemas/models
├── services/ # Business logic services
├── migrations/ # Data migrations
├── index.ts # Component definition with the controllers, repos, schemas and services
└── Component.md # A markdown with notes for later use by other Agents
Each component controller type folder has an index.ts (for example controllers/resolvers/index.ts) that exports an array of classes:
Component Definition
The component definition index.ts is always structured like this:
import {component} from '@orion-js/components'
import resolvers from './controllers/resolvers'
import routes from './controllers/routes'
import jobs from './controllers/jobs'
import echoes from './controllers/echoes'
import modelResolvers from './controllers/modelResolvers'
export default component({
resolvers,
routes,
jobs,
echoes,
modelResolvers,
})
Controllers
Controllers are the entry points for code execution. Keep controllers thin - they should only:
- Handle input validation
- Call the appropriate services
- Transform and return the response
Different types of controllers:
- Route controllers: Handle HTTP endpoints
- GraphQL resolvers: Handle GraphQL operations (preferred over routes for client APIs)
- Job controllers: Handle scheduled or on-demand tasks
- Echo controllers: Handle event-based communication
Resolvers Folder Organization
The resolvers folder should be organized by entity and action:
controllers/
└── resolvers/
├── users/
│ ├── GetUser/index.ts
│ ├── CreateUser/index.ts
│ └── UpdateUser/index.ts
├── orders/
│ ├── GetOrder/index.ts
│ └── CreateOrder/index.ts
└── index.ts
The index.ts exports all resolvers as a single array:
import {GetUserResolvers} from './users/GetUser'
import {CreateUserResolvers} from './users/CreateUser'
import {UpdateUserResolvers} from './users/UpdateUser'
import {GetOrderResolvers} from './orders/GetOrder'
import {CreateOrderResolvers} from './orders/CreateOrder'
export default [
GetUserResolvers,
CreateUserResolvers,
UpdateUserResolvers,
GetOrderResolvers,
CreateOrderResolvers
]
Configuration Structure
The config directory contains application-wide configuration:
config/
├── echoes/ # Event system configuration
├── graphql/ # GraphQL server configuration
├── health/ # Health check endpoints
├── http/ # HTTP server configuration
├── jobs/ # Background job configuration
├── options/ # Application options/settings
└── index.ts # Configuration entry point
Application Bootstrap
The application is bootstrapped in app/index.ts:
import {startApp} from './config'
import exampleComponent from './exampleComponent'
startApp([exampleComponent])
Component.md Management
Component.md serves as a memory store - it contains essential notes that help understand the component without reading all the code.
Structure:
Component.md should contain organized “notes” as bullet points, where each note is 2-5 phrases describing:
- Key business logic and data flows
- Important architectural decisions
- External dependencies and integrations
- Critical implementation details
- Known issues or limitations
- How to check for permissions
- Anything else important about the component
Best Practices:
- BEFORE any task: Read the Component.md file if it exists
- IF no Component.md exists: Create it by reading the whole component folder
- AFTER any schema, service, or controller changes: Update the Component.md with relevant notes
- AFTER adding new features: Document important implementation details
What to include: Only store notes valuable for understanding the component’s purpose, behavior, and important implementation details.
What NOT to include: Avoid temporary information, detailed code explanations, or information easily derived from code structure.
Scripts Directory
For one-off scripts or maintenance tasks, use the temp/scripts directory:
/
├── app/
├── temp/
│ └── scripts/ # Temporary scripts for maintenance tasks
│ ├── migrate-legacy-data.ts
│ └── cleanup-orphaned-records.ts
└── ...
Scripts should:
- Use tsx for execution:
#!/usr/bin/env -S bunx tsx
- Be named according to the task they perform
- Be self-contained and documented
Example script:
#!/usr/bin/env -S npx tsx
import {logger} from '@orion-js/logger'
import {getMongoConnection} from '@orion-js/mongodb'
async function main() {
logger.info('Starting cleanup script')
const connection = getMongoConnection({name: 'main'})
await connection.connectionPromise
// Script logic here
logger.info('Cleanup complete')
process.exit(0)
}
main().catch(error => {
logger.error('Script failed', {error})
process.exit(1)
})
Run with: bunx tsx temp/scripts/cleanup-orphaned-records.ts
Code Organization Guidelines
- File size limit: Avoid files over 200-300 lines of code. Refactor at that point.
- Loop preferences: Prefer
for of or for await of over .forEach. Use .map for transformations.
- Mock data: Mocking data is only needed for tests, never for dev or prod environments.
- Avoid any: Always declare types for variables and function parameters/returns.
- Code duplication: Check for existing similar code before writing new implementations.
Basic Principles
- Use component-based architecture
- Encapsulate functionality in components
- One component per main domain
- Each component should contain controllers, schemas, services, and repositories
- Prefer usage of resolvers instead of routes
- Use dependency injection for service dependencies with
@Inject() decorator
- Follow the single responsibility principle for services
- Use repositories for database operations
- Handle validation and error cases appropriately
- Prefer throwing
ValidationError when validation of data fails
- Prefer throwing
UserError when the error is not a system error