@eyjs/create-app
Version:
CLI tool to generate hexagonal folder structure for EyJS applications
369 lines (295 loc) ⢠9.48 kB
Markdown
//badge.fury.io/js/%40eyjs%2Fcreate-app.svg)](https://badge.fury.io/js/%40eyjs%2Fcreate-app)
[](https://opensource.org/licenses/MIT)
CLI tool to generate hexagonal architecture folder structure for EyJS applications. Quickly scaffold new projects with domain-driven design principles and clean architecture patterns.
- šļø **Hexagonal Architecture** - Generates clean architecture folder structure
- šÆ **Domain-Driven Design** - Follows DDD principles with proper separation of concerns
- š **Automated Scaffolding** - Creates all necessary files and folders automatically
- š§ **TypeScript Support** - Full TypeScript setup with proper type definitions
- ā” **Zero Configuration** - Works out of the box with sensible defaults
- šØ **Customizable Templates** - Flexible template system for different project types
```bash
bun add -g @eyjs/create-app
npm install -g @eyjs/create-app
yarn global add @eyjs/create-app
pnpm add -g @eyjs/create-app
```
```bash
create-eyjs-app my-awesome-app
create-eyjs-app my-app --path ./projects
create-eyjs-app my-app --template api
```
The CLI generates a complete hexagonal architecture structure:
```
my-app/
āāā application/
ā āāā services/
ā ā āāā my-app.service.ts
ā āāā dtos/
ā ā āāā create-my-app.dto.ts
ā āāā interfaces/
ā āāā my-app.repository.interface.ts
āāā domain/
ā āāā entities/
ā ā āāā my-app.entity.ts
ā āāā value-objects/
ā ā āāā id.value-object.ts
ā āāā events/
ā ā āāā my-app-created.event.ts
ā āāā interfaces/
ā āāā my-app.repository.interface.ts
āāā infrastructure/
ā āāā controllers/
ā ā āāā my-app.controller.ts
ā āāā repositories/
ā ā āāā my-app-mongo.repository.ts
ā āāā middleware/
ā ā āāā validation.middleware.ts
ā āāā config/
ā āāā database.config.ts
āāā shared/
ā āāā errors/
ā āāā types/
ā āāā utils/
āāā tests/
ā āāā unit/
ā āāā integration/
ā āāā e2e/
āāā package.json
āāā tsconfig.json
āāā .env.example
āāā README.md
```
```bash
create-eyjs-app <app-name> [options]
Options:
--path <path> Specify the directory to create the app
--template <name> Choose a template (api, web, microservice)
--skip-install Skip dependency installation
--help Show help information
--version Show version information
```
### Available Templates
| Template | Description | Use Case |
|----------|-------------|----------|
| `api` | REST API with controllers | Backend APIs, microservices |
| `web` | Full-stack web application | Web applications with frontend |
| `microservice` | Microservice with event bus | Event-driven microservices |
## Generated Files
### Application Layer
**Service (`application/services/my-app.service.ts`)**
```typescript
import { Injectable } from '@eyjs/core'
import { MyAppRepository } from '../interfaces/my-app.repository.interface'
import { CreateMyAppDto } from '../dtos/create-my-app.dto'
@Injectable()
export class MyAppService {
constructor(private readonly repository: MyAppRepository) {}
async create(dto: CreateMyAppDto) {
// Business logic implementation
}
async findById(id: string) {
// Find by ID logic
}
}
```
**DTO (`application/dtos/create-my-app.dto.ts`)**
```typescript
export interface CreateMyAppDto {
name: string
description?: string
// Additional fields
}
```
**Entity (`domain/entities/my-app.entity.ts`)**
```typescript
import { IdValueObject } from '../value-objects/id.value-object'
export class MyAppEntity {
constructor(
public readonly id: IdValueObject,
public readonly name: string,
public readonly description?: string
) {}
static create(name: string, description?: string) {
return new MyAppEntity(
IdValueObject.generate(),
name,
description
)
}
}
```
**Value Object (`domain/value-objects/id.value-object.ts`)**
```typescript
import { v4 as uuidv4 } from 'uuid'
export class IdValueObject {
constructor(private readonly value: string) {
if (!this.isValid(value)) {
throw new Error('Invalid ID format')
}
}
static generate(): IdValueObject {
return new IdValueObject(uuidv4())
}
toString(): string {
return this.value
}
private isValid(value: string): boolean {
// UUID validation logic
return true
}
}
```
**Controller (`infrastructure/controllers/my-app.controller.ts`)**
```typescript
import { Controller, Get, Post } from '@eyjs/http-server'
import { MyAppService } from '../../application/services/my-app.service'
import { CreateMyAppDto } from '../../application/dtos/create-my-app.dto'
@Controller('/my-app')
export class MyAppController {
constructor(private readonly service: MyAppService) {}
@Post()
async create(dto: CreateMyAppDto) {
return await this.service.create(dto)
}
@Get('/:id')
async findById(id: string) {
return await this.service.findById(id)
}
}
```
**Repository (`infrastructure/repositories/my-app-mongo.repository.ts`)**
```typescript
import { Injectable } from '@eyjs/core'
import { MyAppRepository } from '../../domain/interfaces/my-app.repository.interface'
import { MyAppEntity } from '../../domain/entities/my-app.entity'
@Injectable()
export class MyAppMongoRepository implements MyAppRepository {
async save(entity: MyAppEntity): Promise<void> {
// MongoDB implementation
}
async findById(id: string): Promise<MyAppEntity | null> {
// MongoDB find implementation
}
}
```
```json
{
"name": "my-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "bun run --watch src/index.ts",
"build": "tsc",
"start": "bun run src/index.ts",
"test": "bun test"
},
"dependencies": {
"@eyjs/core": "^1.0.4"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
```
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/application/*": ["./src/application/*"],
"@/domain/*": ["./src/domain/*"],
"@/infrastructure/*": ["./src/infrastructure/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
```
```bash
create-eyjs-app user-api --template api
create-eyjs-app ecommerce-web --template web
create-eyjs-app notification-service --template microservice
```
```bash
create-eyjs-app my-app --path ./backend-services
```
```bash
create-eyjs-app my-app --skip-install
```
The generated applications are fully compatible with the EyJS ecosystem:
```typescript
// Generated app automatically includes EyJS core
import { EyJs } from '@eyjs/core'
// Dependency injection works out of the box
@Injectable()
export class MyService {
// Auto-injected dependencies
}
// HTTP server integration
import { Controller, Get } from '@eyjs/http-server'
@Controller('/api')
export class ApiController {
// HTTP endpoints
}
```
- Keep business logic in the domain layer
- Use value objects for complex data types
- Implement domain events for side effects
- Dependencies point inward (toward domain)
- Use interfaces for external dependencies
- Keep infrastructure concerns separate
### Testing Strategy
- Unit tests for domain logic
- Integration tests for repositories
- E2E tests for API endpoints
## Contributing
Contributions are welcome! Please read our [Contributing Guide](https://github.com/elevenyellow/EyJS-core/blob/main/CONTRIBUTING.md) for details.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
- š [Documentation](https://github.com/elevenyellow/EyJS-core#readme)
- š [Issue Tracker](https://github.com/elevenyellow/EyJS-core/issues)
- š¬ [Discussions](https://github.com/elevenyellow/EyJS-core/discussions)
[![npm version](https: