Skip to main content

Development

Local development setup and workflows for AsaHome Cloud.

Prerequisites

  • Node.js 20+ (LTS recommended)
  • npm 9+ or yarn 1.22+
  • Docker and Docker Compose
  • PostgreSQL 16+ (or use Docker)
  • Git

Initial Setup

1. Clone Repository

git clone <repository-url>
cd asahome-cloud

2. Install Dependencies

npm install

3. Environment Configuration

# Copy example environment file
cp env.example .env

# Generate development JWT secret
echo "JWT_SECRET=$(openssl rand -base64 32)" >> .env

Edit .env for development:

NODE_ENV=development
PORT=3000

# Database
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE=asahome_cloud_dev
DB_SYNCHRONIZE=false
DB_LOGGING=true

# JWT
JWT_SECRET=your-development-secret
JWT_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=7d

# CORS
CORS_ORIGINS=*

# Rate limiting (relaxed for development)
THROTTLE_TTL=60
THROTTLE_LIMIT=1000

4. Start Database

Using Docker (recommended):

docker run -d \
--name asahome-postgres-dev \
-p 5432:5432 \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=asahome_cloud_dev \
-v asahome_pg_data:/var/lib/postgresql/data \
postgres:16-alpine

Or use Docker Compose:

docker-compose up -d postgres

5. Run Migrations

npm run migration:run

6. Start Development Server

npm run start:dev

The API will be available at http://localhost:3000/api/v1

API Base URL: http://localhost:3000/api/v1

Makefile Commands

CommandDescription
make setupInitial project setup
make devStart development environment
make upStart all containers
make downStop all containers
make logsView all logs
make logs-appView application logs
make healthCheck service health
make shell-dbOpen PostgreSQL shell
make shell-appOpen application shell
make testRun tests
make lintRun linter
make formatFormat code
make cleanRemove containers and volumes

npm Scripts

ScriptDescription
npm run startStart production server
npm run start:devStart with hot reload
npm run start:debugStart with debugging
npm run buildBuild for production
npm run lintRun ESLint
npm run formatFormat with Prettier
npm testRun unit tests
npm run test:watchRun tests in watch mode
npm run test:covRun tests with coverage
npm run test:e2eRun e2e tests

Database Migrations

Create New Migration

npm run migration:generate -- -n MigrationName

This creates a new migration file in src/migrations/.

Run Migrations

npm run migration:run

Revert Last Migration

npm run migration:revert

Show Migration Status

npm run migration:show

Migration Example

// src/migrations/1700000000000-AddDeviceMetadata.ts
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm';

export class AddDeviceMetadata1700000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.addColumn(
'devices',
new TableColumn({
name: 'metadata',
type: 'jsonb',
isNullable: true,
}),
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropColumn('devices', 'metadata');
}
}

Git Workflow

Branch Strategy

main          # Production branch (protected)
├── dev # Development branch
│ ├── feature/add-devices
│ ├── feature/websocket-auth
│ └── fix/token-refresh

Commit Messages

Follow conventional commits:

feat: add device registration endpoint
fix: correct token refresh logic
docs: update API documentation
refactor: simplify auth service
test: add device controller tests
chore: update dependencies

Pull Request Workflow

  1. Create feature branch from dev
  2. Make changes and commit
  3. Push and create PR to dev
  4. Get code review
  5. Merge to dev
  6. When ready, create PR from dev to main

Code Style

ESLint Configuration

ESLint is configured in .eslintrc.js:

module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
},
};

Prettier Configuration

Prettier is configured in .prettierrc:

{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"semi": true
}

Pre-commit Hooks

Husky and lint-staged are configured:

// package.json
{
"lint-staged": {
"*.ts": [
"eslint --fix",
"prettier --write"
]
}
}

Debugging

VS Code Configuration

Create .vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug NestJS",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "start:debug"],
"console": "integratedTerminal",
"restart": true,
"autoAttachChildProcesses": true
}
]
}

Debug with Chrome DevTools

npm run start:debug

Open chrome://inspect in Chrome and connect to the Node.js process.

Logging

Enable verbose logging in development:

# .env
DB_LOGGING=true
DEBUG=nest:*

Common Development Tasks

Add New Module

# Generate module
npx nest g module feature-name

# Generate controller
npx nest g controller feature-name

# Generate service
npx nest g service feature-name

Add New Entity

  1. Create entity file:
// src/feature-name/entities/feature.entity.ts
@Entity('features')
export class Feature {
@PrimaryGeneratedColumn('uuid')
id: string;

@Column()
name: string;

@CreateDateColumn()
createdAt: Date;
}
  1. Add to module:
@Module({
imports: [TypeOrmModule.forFeature([Feature])],
})
export class FeatureModule {}
  1. Generate migration:
npm run migration:generate -- -n AddFeature
npm run migration:run

Test API Endpoints

Use Postman or curl to test endpoints:

# Login
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "password123"}'

# Use token for authenticated requests
curl -X GET http://localhost:3000/api/v1/users/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Troubleshooting

Port Already in Use

# Find process using port
lsof -i :3000

# Kill process
kill -9 <PID>

Database Connection Issues

# Check if PostgreSQL is running
docker ps | grep postgres

# View database logs
docker logs asahome-postgres-dev

# Restart database
docker restart asahome-postgres-dev

Module Not Found

# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

# Clear NestJS cache
rm -rf dist
npm run build

Migration Errors

# Check migration status
npm run migration:show

# Revert and rerun
npm run migration:revert
npm run migration:run