Kimesh Code Standards & Guidelines
Version: 0.2.23 Effective: January 28, 2026 Scope: All packages in /packages/, /modules/, and /tooling/ directories
Overview
This document establishes coding standards, conventions, and best practices for the Kimesh monorepo. All contributions must adhere to these guidelines to maintain consistency, readability, and maintainability across the codebase.
File Organization
Directory Structure
Each package follows this standard structure:
packages/package-name/
├── src/
│ ├── index.ts # Main export file
│ ├── types.ts # Type definitions
│ ├── [feature-name]/
│ │ ├── index.ts # Feature export
│ │ ├── [implementation].ts # Implementation details
│ │ └── [implementation].test.ts # Tests
│ ├── [feature].ts # Single-file features
│ ├── [feature].test.ts # Feature tests
│ └── utils/ # Shared utilities
│ ├── index.ts
│ └── [utility].ts
├── package.json # Package metadata
├── tsconfig.json # TypeScript config
├── tsdown.config.ts # Build config
├── README.md # Package documentation
├── augment.d.ts # Vue type augmentation (optional)
└── .test/ # Test fixtures (optional)Module Definition Pattern
Modules in /modules/ follow the same structure with additional:
src/module.ts- Module configuration/factorysrc/plugin.ts- Plugin definitionaugment.d.ts- Framework augmentation
File Naming
Directories: kebab-case
✓ src/route-generator/ ✓ src/auto-import/ ✗ src/routeGenerator/ ✗ src/autoImport/Files: kebab-case
✓ route-merger.ts ✓ oxc-scanner.ts ✓ conflict-resolver.ts ✗ routeMerger.ts ✗ oxcScanner.tsTest Files:
[name].test.ts✓ route-merger.ts + route-merger.test.ts ✓ plugin.ts + plugin.test.ts ✗ route-merger-test.ts ✗ route-merger.spec.tsPrivate/Internal Files: Leading underscore
✓ _internal-helpers.ts ✓ _shared-utils.ts ✗ internal-helpers.ts (if not exported)Type Definition Files:
types.ts✓ src/types.ts (type definitions) ✓ src/types/config.ts (organized types) ✗ src/types.ts + src/interfaces.ts (mixed naming)Index Files: Always
index.ts✓ src/index.ts ✓ src/feature/index.ts ✗ src/main.ts ✗ src/feature/main.ts
File Size & Complexity
Size Limits
- Maximum 200 lines per file (soft limit, hard stops at 250)
- Rationale: Improves readability, easier testing, clearer responsibility
- Exceptions: Test files may exceed with complex test suites, but split when over 300 lines
Complexity Guidelines
- Maximum cyclomatic complexity: 10
- Maximum nesting depth: 4 levels
- Maximum function length: 50 lines (aim for 20-30)
- Maximum parameters: 4 (use objects for 5+)
Metrics
// ✓ Good: Clear responsibility, single purpose
export function generateRoute(config: RouteConfig): Route {
// ~20 lines
}
// ✗ Poor: Too many responsibilities
export function generateAndValidateAndOptimizeAndSerialize(
config: RouteConfig,
validation: boolean,
optimize: boolean,
format: string,
): Route {
// ~200 lines of mixed concerns
}TypeScript Standards
Strict Mode Required
All packages must have TypeScript strict mode enabled:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}Type Definitions
Always export types from types.ts:
// src/types.ts
export interface RouteConfig {
path: string
component?: Component
meta?: Record<string, any>
}
export interface Route extends RouteConfig {
children?: Route[]
id: string
}
// src/router-generator.ts
import type { RouteConfig, Route } from './types'
export function generateRoute(config: RouteConfig): Route {
// ...
}Use specific types, not any:
// ✓ Good
function processRoute(route: Route): string {
return route.path
}
// ✗ Poor
function processRoute(route: any): any {
return route.path
}Use unknown instead of any for flexibility:
// ✓ Good for generic handlers
function handle(data: unknown): void {
if (typeof data === 'string') {
// ...
}
}
// ✗ Poor
function handle(data: any): void {
// ...
}Naming Conventions
Functions & Variables
camelCase for all functions and variables
typescript✓ export function generateRoutes() {} ✓ const routeConfig = {} ✓ let currentIndex = 0PascalCase for classes and components
typescript✓ export class RouteGenerator {} ✓ export const KmHead = defineComponent({}) ✓ const MyComponent = () => {}UPPER_SNAKE_CASE for constants
typescript✓ export const MAX_FILE_SIZE = 1024 * 1024 ✓ const DEFAULT_TIMEOUT_MS = 5000Interfaces: PascalCase, optional
Iprefixtypescript✓ interface RouteDefinition {} ✓ interface IKimeshConfig {} ✓ type RouteOptions = {}Imports: Match export naming
typescript✓ import { RouteGenerator } from './generator' ✓ import type { RouteConfig } from './types' ✓ import { MAX_FILE_SIZE } from './constants'
Vue Components
PascalCase for component names
typescript✓ export const KmHead = defineComponent({}) ✓ export const KmLink = defineComponent({}) ✗ export const kmHead = defineComponent({})kebab-case for component files
✓ src/components/km-head.ts ✓ src/components/km-link.ts ✗ src/components/KmHead.ts ✗ src/components/kmHead.ts
Import/Export Patterns
Export Order
Organize exports in this order:
// 1. Type-only exports first
export type { RouteConfig, Route, RouteDefinition }
// 2. Interface exports
export interface { RouterContext }
// 3. Constant exports
export const MAX_ROUTES = 1000
export const DEFAULT_TIMEOUT = 5000
// 4. Function exports
export function generateRoute(config: RouteConfig): Route {}
export function validateRoute(route: Route): boolean {}
// 5. Class exports
export class RouteGenerator {
// ...
}
// 6. Re-exports from other modules
export * from './utils'
export * from './helpers'Named Exports Only
Avoid default exports for consistency:
// ✓ Good: Named exports
export function generateRoute() {}
export interface RouteConfig {}
export class RouteGenerator {}
// Later: Selective imports
import { generateRoute, RouteGenerator } from './route-generator'
// ✗ Poor: Default exports
export default function generateRoute() {}
export default class RouteGenerator {}
// Later: Unclear what is exported
import generateRoute from './route-generator'Exception: Main index.ts files may have appropriate re-exports.
Path Aliases
Use path aliases from tsconfig.json:
// ✓ Good
import type { RouteConfig } from '@kimesh/kit/types'
import { generateRoute } from '@/route-generator'
// ✗ Poor (relative paths in deeply nested files)
import type { RouteConfig } from '../../../../../../../types'
import { generateRoute } from '../../route-generator'Type-Only Imports
Always use type keyword for type imports:
// ✓ Good: Tree-shaking aware
import type { RouteConfig, Route } from './types'
import { generateRoute } from './generator'
// ✗ Poor: Unnecessary runtime imports
import { RouteConfig, Route } from './types'Testing Standards
Test Coverage Requirements
- Minimum coverage: 90% across all packages
- Core packages (kit, router-generator, auto-import): 95%+
- Integration tests: Required for major features
Test File Organization
// route-merger.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { mergeRoutes } from './route-merger'
import type { Route } from './types'
describe('mergeRoutes', () => {
let routes: Route[]
beforeEach(() => {
routes = []
})
describe('basic functionality', () => {
it('should merge simple routes', () => {
// Arrange
const route1: Route = { path: '/', id: '1' }
const route2: Route = { path: '/about', id: '2' }
// Act
const result = mergeRoutes([route1, route2])
// Assert
expect(result).toHaveLength(2)
})
it('should preserve route order', () => {
// ...
})
})
describe('edge cases', () => {
it('should handle empty array', () => {
// ...
})
it('should handle duplicate paths', () => {
// ...
})
})
})Test Naming Conventions
- Test files:
[feature].test.ts - Describe blocks: Feature or context name
- Test cases: Start with verb (should, must, handles)
// ✓ Good
describe('RouteGenerator', () => {
it('should generate valid routes from config', () => {})
it('should throw error for invalid path', () => {})
it('handles nested routes correctly', () => {})
})
// ✗ Poor
describe('test route generation', () => {
it('works', () => {})
it('error handling', () => {})
})Mocking Patterns
// Use vi.mock() for module mocking
import { vi, describe, it, expect } from 'vitest'
vi.mock('./dependency', () => ({
getDependency: vi.fn().mockReturnValue({}),
}))
// Use vi.fn() for function mocking
const mockFn = vi.fn()
mockFn.mockReturnValue('value')
mockFn.mockImplementation((arg) => arg * 2)Module Definition Standards
Package.json Structure
{
"name": "@kimesh/package-name",
"version": "0.2.23",
"description": "Clear, concise description of package purpose",
"repository": {
"type": "git",
"url": "https://github.com/kimeshjs/kimesh.git"
},
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": ["dist", "types.d.ts"],
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest run"
},
"dependencies": {
"@kimesh/other-package": "workspace:*"
},
"devDependencies": {
"typescript": "^5.8.3",
"tsdown": "^0.20.0-beta.3"
},
"peerDependencies": {
"vue": "^3.5.0"
}
}Module Export Structure
// src/index.ts - Main entry point
export * from './types'
export * from './feature1'
export * from './feature2'
export * from './utils'
// src/types.ts - All type definitions
export interface ModuleConfig {}
export type ModuleOptions = {}
// src/feature.ts - Single feature
export function feature() {}
// src/feature/index.ts - Complex feature
export * from './implementation'
export * from './helpers'Error Handling
Error Types
Use specific error classes:
// ✓ Good: Specific error types
export class InvalidRouteError extends Error {
constructor(
message: string,
public route: Route,
) {
super(message)
this.name = 'InvalidRouteError'
}
}
export class ConfigValidationError extends Error {
constructor(
message: string,
public config: unknown,
) {
super(message)
this.name = 'ConfigValidationError'
}
}
// Usage
if (!isValidRoute(route)) {
throw new InvalidRouteError('Route path is invalid', route)
}Error Messages
- Clear and actionable: Describe what went wrong and why
- Include context: Show the problematic values
- Suggest fixes: When possible, indicate how to resolve
// ✓ Good
throw new Error(
`Invalid route path "${route.path}". ` + `Expected route path to start with "/" but got "${route.path.charAt(0)}".`,
)
// ✗ Poor
throw new Error('Bad route')
throw new Error('Route error')Documentation Standards
Function Documentation
Use JSDoc for all public functions:
/**
* Generates route configuration from file-based structure.
*
* @param config - The route configuration object
* @param options - Optional generation options
* @returns Generated route object with nested children
* @throws {InvalidRouteError} If the configuration is invalid
*
* @example
* ```typescript
* const route = generateRoute({ path: '/' })
* ```
*/
export function generateRoute(config: RouteConfig, options?: GenerationOptions): Route {
// ...
}Type Documentation
Document complex types and interfaces:
/**
* Configuration options for route generation.
*
* @property path - The route path (required, must start with /)
* @property component - Vue component for the route (optional)
* @property meta - Route metadata for middleware/guards (optional)
* @property children - Nested routes (optional)
*/
export interface RouteConfig {
path: string
component?: Component
meta?: Record<string, any>
children?: RouteConfig[]
}Code Formatting
Format & Lint Configuration
The project uses automated formatting and linting:
- Formatter: oxfmt (Rust-based)
- Linter: oxlint (Rust-based)
- Run before commit:
pnpm fmt && pnpm lint:fix
Commands:
# Check formatting
pnpm fmt:check
# Auto-format
pnpm fmt
# Check linting
pnpm lint
# Fix linting issues
pnpm lint:fix
# Full validation
pnpm fmt:check && pnpm lint && pnpm typecheckIndentation & Style
- Indent: 2 spaces (enforced by oxfmt)
- Line length: 100 characters (soft), 120 (hard)
- Semicolons: Required (enforced by oxlint)
- Trailing commas: ES5-style (enforced by oxfmt)
Performance Considerations
Build Performance
- Use tree-shaking compatible exports (named exports)
- Avoid circular dependencies
- Minimize runtime overhead from generated code
- Use lazy imports for optional features
Runtime Performance
- Cache computed values when appropriate
- Minimize re-renders in Vue components
- Use composition API for optimal tree-shaking
- Avoid inline function definitions in templates
Version Management
Versioning Scheme
Kimesh follows semantic versioning:
MAJOR.MINOR.PATCH (e.g., 0.2.23)
- MAJOR: Breaking API changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatibleDependency Updates
- Use
workspace:*for internal monorepo dependencies - Pin exact versions for external dependencies in package.json
- Update dependencies monthly during development
- Security updates immediately
Code Review Checklist
Before submitting a PR, verify:
- [ ] All files follow naming conventions
- [ ] No file exceeds 200 lines (except tests/docs)
- [ ] TypeScript strict mode passes
- [ ] Test coverage >= 90%
- [ ] All tests pass:
pnpm test - [ ] Code formatted:
pnpm fmt - [ ] Linting passes:
pnpm lint - [ ] Type checking passes:
pnpm typecheck - [ ] Documentation updated
- [ ] Error messages are clear and actionable
- [ ] No console.log statements (use proper logging)
- [ ] No commented-out code
Continuous Enforcement
These standards are enforced by:
- Pre-commit hooks (when configured)
- GitHub Actions CI (pull request checks)
- Code review process (manual verification)
- Automated tooling (oxfmt, oxlint, Vitest)
All contributions must pass these checks before merging.