Naming Conventions
File Naming — PascalCase (STRICTLY ENFORCED)
All TypeScript files use PascalCase — no kebab-case, no type suffixes like .entity.ts, .vo.ts, or .service.ts.
| Type | Pattern | Examples |
|---|---|---|
| Entities | [Entity].ts | CexAccount.ts, CoinBlockchain.ts, Pair.ts |
| Value Objects | [ValueObject].ts | CexAccountId.ts, CexAccountAuth.ts, CoinId.ts |
| App Services | [Action][Target].ts | CoinBlockchainCreator.ts, CexCoinBlockchainStatusUpdater.ts |
| Domain Services | [Domain][Concept].ts | PairsBuilder.ts, CoinPairMarketPathCalculator.ts |
| Repo Interface | [Entity]Repository.ts | CexAccountRepository.ts, PairRepository.ts |
| Prisma Repo | [Entity]PrismaRepository.ts | CexAccountPrismaRepository.ts |
| InMemory Repo | [Entity]InMemoryRepository.ts | PairInMemoryRepository.ts |
| Domain Events | [Subject][Action]DomainEvent.ts | CoinBlockchainCreatedDomainEvent.ts |
| Event Subscribers | [Action]On[Event].ts | UpdateCexCoinsBlockchainsOnCoinBlockchainCreated.ts |
| Factories | [Entity]Factory.ts | CexAccountFactory.ts, CexCoinBlockchainFactory.ts |
| Test Builders | [Entity]Mother.ts | CexAccountMother.ts, CexCoinBlockchainMother.ts |
| Adapters | [Tech][Port]Adapter.ts | CctxCexSpotAccountAdapter.ts |
| Ports | [Subject]Port.ts | CexSpotAccountPort.ts |
| Controllers | [Entity][Action]Controller.ts | CexAccountFinderController.ts |
Class Naming
Always PascalCase matching the filename:
typescript
// CexAccountPrismaRepository.ts
export class CexAccountPrismaRepository { ... }
// CoinBlockchainCreator.ts
export class CoinBlockchainCreator { ... }
// UpdateCexCoinsBlockchainsOnCoinBlockchainCreated.ts
export class UpdateCexCoinsBlockchainsOnCoinBlockchainCreated { ... }Method Naming
Always camelCase. Services MUST have a public run() method as the main entry point:
typescript
class CoinBlockchainCreator {
async run({ coinId, blockchain }: CreateParams): Promise<CoinBlockchain> { ... }
private validate(params: CreateParams): void { ... }
}
class CexAccountRepository {
findById(id: string): Promise<CexAccount | null>
findAll(): Promise<CexAccount[]>
save(account: CexAccount): Promise<void>
delete(id: string): Promise<void>
}Package Naming
Always @sws/package-name:
typescript
import { LoggerFactory } from '@sws/common/logger'
import type { DomainEventSubscriber } from '@sws/common/domain'
import { CexAccountFactory } from '@sws/cex-wallets'
import { client as prisma } from '@sws/database'Directory Naming
Directories use camelCase:
domain/entities/domain/valueObjects/(notvalue-objects/)domain/repositories/domain/services/domain/events/domain/ports/application/services/application/eventSubscribers/(notevent-subscribers/)infrastructure/repositories/infrastructure/adapters/infrastructure/factories/infrastructure/controllers/
Event Naming Convention
Event names (the string eventName) use kebab-case dot-separated:
typescript
static eventName = 'cex-wallets.coinBlockchainCreated'
static eventName = 'rates.pairsRegenerated'
static eventName = 'shifts.tradesCompleted'Format: <bounded-context>.<subjectAction>
