JavaScript Standards
JavaScript Standards
Section titled “JavaScript Standards”1. Package Management
Section titled “1. Package Management”- Tool:
pnpmpreferred,npmacceptable. Lock files committed. - Version: ES2022+ features. Use modern syntax.
- Config:
.nvmrcor.node-versionto pin Node.js version.
2. Code Style
Section titled “2. Code Style”- Formatter:
prettierwith line length 120. Run viamake fmt. - Linter:
eslintwith recommended rules. Useeslint-config-prettierto avoid conflicts. - Type Checking: Use JSDoc with
@ts-checkor migrate to TypeScript.
.eslintrc.js
Section titled “.eslintrc.js”module.exports = { env: { es2022: true, node: true, }, extends: ['eslint:recommended', 'prettier'], parserOptions: { ecmaVersion: 2022, sourceType: 'module', }, rules: { 'no-unused-vars': 'error', 'no-console': 'warn', },};3. Naming Conventions
Section titled “3. Naming Conventions”- Files:
kebab-case.jsorkebab-case.mjs - Classes:
PascalCase - Variables/Functions:
camelCase - Constants:
UPPER_SNAKE_CASEorcamelCasewithconst - Private:
_leadingUnderscore(convention only)
4. Project Structure
Section titled “4. Project Structure”src/├── domain/│ ├── entities/│ └── value-objects/├── application/│ ├── use-cases/│ └── interfaces/└── infrastructure/ └── repositories/5. Modern JavaScript
Section titled “5. Modern JavaScript”- ES Modules: Use
import/export. Avoid CommonJSrequire(). - Const/Let: Always use
const. Useletonly when reassignment needed. Never usevar. - Arrow Functions: Prefer arrow functions for callbacks. Use regular functions for methods.
- Destructuring: Use destructuring for objects and arrays.
- Template Literals: Use template strings instead of concatenation.
Example
Section titled “Example”class Email { #value;
constructor(value) { if (!/^[^@]+@[^@]+\.[^@]+$/.test(value)) { throw new InvalidEmailError(value); } this.#value = value; }
toString() { return this.#value; }}
class Result { static success(data) { return { success: true, data }; }
static failure(error) { return { success: false, error }; }}6. Error Handling
Section titled “6. Error Handling”- Custom Errors: Extend
Errorclass. Use typed error classes. - Try-Catch: Always handle errors. Use
try-catchfor synchronous,catch()for promises. - Error Context: Include context in error messages.
class DomainError extends Error { constructor(message, cause) { super(message); this.name = this.constructor.name; this.cause = cause; Error.captureStackTrace(this, this.constructor); }}
class InvalidEmailError extends DomainError { constructor(email) { super(`Invalid email: ${email}`); this.email = email; }}7. Testing
Section titled “7. Testing”- Framework:
vitestorjest. Use@testing-libraryfor DOM testing. - Mocking: Use framework’s built-in mocking. Mock external dependencies.
- Coverage: 95% is the absolute minimum for any module. Target 100% for domain, 95%+ for application and infrastructure.
Test Structure
Section titled “Test Structure”import { describe, it, expect, vi } from 'vitest';import { UserService } from './user-service.js';import { Email } from './domain/email.js';
describe('UserService', () => { it('should create user with valid email', () => { // Given const email = new Email('test@example.com');
// When const user = UserService.createUser(email, 'Test User');
// Then expect(user.email.toString()).toBe('test@example.com'); });});8. Async/Await
Section titled “8. Async/Await”- Promises: Use
async/awaitover.then(). UsePromise.all()for parallel operations. - Error Handling: Always handle promise rejections. Use
try-catchwith async functions.
async function fetchUser(id) { try { const user = await userRepository.findById(id); if (!user) { throw new UserNotFoundException(id); } return user; } catch (error) { if (error instanceof DomainError) { throw error; } throw new UserFetchError(`Failed to fetch user: ${id}`, error); }}9. Dependencies
Section titled “9. Dependencies”Common Libraries
Section titled “Common Libraries”- HTTP:
axiosorfetch(native) - Validation:
zodfor runtime validation - State Management: Framework-specific or
zustand - Logging:
pinoorwinston
10. Documentation
Section titled “10. Documentation”- JSDoc: Use JSDoc comments for public APIs. Generate docs with
jsdoc. - Format: Use
@param,@returns,@throwstags.
/** * Creates a new user with validated email address. * * @param {Email} email - Valid email address (must match RFC 5322) * @param {string} name - User's full name (non-null, non-empty) * @returns {User} New User entity instance * @throws {InvalidEmailError} If email format is invalid * @example * ```js * const user = createUser(new Email('test@example.com'), 'John Doe'); * ``` */function createUser(email, name) { // Implementation}11. Node.js Specific
Section titled “11. Node.js Specific”- ES Modules: Use
.mjsextension or"type": "module"inpackage.json. - File System: Use
fs/promisesfor async file operations. - Environment Variables: Use
dotenvfor local development. Validate withzod.
12. Browser Specific
Section titled “12. Browser Specific”- Bundling: Use
vite,esbuild, orwebpackfor bundling. - Polyfills: Use
core-jsor@babel/polyfillfor older browsers if needed. - Transpilation: Use
babelorswcfor transforming code.
13. Best Practices
Section titled “13. Best Practices”- Immutability: Prefer immutable data structures. Use
Object.freeze()for constants. - Pure Functions: Write pure functions when possible. Avoid side effects.
- Single Responsibility: Functions should do one thing. Keep functions small.
- Early Returns: Use early returns to reduce nesting.