Skip to content

Code Style Standards

Maintain consistent code style using Prettier (formatting) and ESLint (code quality). Ignis provides centralized configurations via the @venizia/dev-configs package.

Quick Reference

AspectStandard
Interface prefixI (e.g., IUserService)
Type alias prefixT (e.g., TUserRequest)
Class namingPascalCase with suffix (e.g., UserController)
File namingkebab-case (e.g., user.controller.ts)
Private fieldsUnderscore prefix (_dataSource)
Binding keys@app/[component]/[feature]
ConstantsStatic readonly class (not enums)
Barrel exportsindex.ts at every folder level
Error format[ClassName][method] Message
Logging format[method] Message | Key: %s
Default optionsDEFAULT_OPTIONS constant
Type safetyNo any or unknown allowed
Scope namingClassName.name
ArgumentsOptions object (opts)
ExportsNamed exports only
Return typesExplicitly defined
Control flowAlways use braces ({})
Switch statementsBraces + default case required
ImportsNode → Third-party → Internal → Relative
Function naminggenerate*, build*, to*, is*, extract*

Sections

SectionDescription
ToolingESLint, Prettier, TypeScript configuration
Naming ConventionsClasses, files, types, binding keys
Type SafetyAvoiding any, explicit returns, generics
Function PatternsOptions object, naming, exports
Route DefinitionsConfig-driven routes, OpenAPI integration
Constants & ConfigurationStatic classes vs enums, defaults
Control Flow & OrganizationBraces, switches, imports, logging
Advanced PatternsMixins, factories, value resolvers
Documentation (JSDoc)When and how to document code

Essential Examples

Naming

typescript
// Interfaces use 'I' prefix
interface IUserService { }

// Type aliases use 'T' prefix
type TUserRequest = { };

// Classes use PascalCase with suffix
class UserController extends BaseController { }
class UserService extends BaseService { }
class UserRepository extends BaseRepository { }

File Structure

src/components/auth/
├── index.ts              # Barrel exports
├── component.ts          # IoC binding
├── controller.ts         # Routes
└── common/
    ├── index.ts
    ├── keys.ts           # Binding keys
    └── types.ts          # Interfaces

Constants (Static Class vs Enum)

typescript
// ✅ GOOD - Static class (tree-shakable)
export class UserStatuses {
  static readonly ACTIVE = 'active';
  static readonly INACTIVE = 'inactive';
}

// ❌ AVOID - Enum (not tree-shakable)
enum UserStatus {
  ACTIVE = 'active',
  INACTIVE = 'inactive',
}

Import Order

typescript
// 1. Node built-ins
import fs from 'node:fs';

// 2. Third-party
import { z } from '@hono/zod-openapi';

// 3. Internal absolute
import { getError } from '@venizia/ignis-helpers';

// 4. Relative (same feature)
import { QueryBuilder } from './query';

See Also