Skip to content

Development

cyclonite69 edited this page Feb 7, 2026 · 1 revision

Development Guide

Complete guide for ShadowCheck development


Prerequisites

  • Node.js 20+ (LTS recommended)
  • PostgreSQL 18+ with PostGIS extension
  • Docker (optional, for containerized development)
  • Git

Initial Setup

1. Clone Repository

git clone https://github.com/cyclonite69/shadowcheck-static.git
cd shadowcheck-static

2. Install Dependencies

npm install

3. Configure Environment

cp .env.example .env
# Edit .env with your database credentials

4. Set Secrets

node scripts/set-secret.js db_password "your-password"
node scripts/set-secret.js db_admin_password "admin-password"
node scripts/set-secret.js mapbox_token "pk.your-token"

5. Run Migrations

psql -U shadowcheck_admin -d shadowcheck_db -f sql/migrations/20260129_implement_db_security.sql

6. Start Development

# Terminal 1: Backend
npm run dev

# Terminal 2: Frontend
npm run dev:frontend

DevContainer Setup (Recommended)

Prerequisites

  • Docker Desktop
  • VS Code with Dev Containers extension

Steps

  1. Open in DevContainer (VS Code will prompt)
  2. Wait for container build
  3. Start developing:
    npm run dev          # Backend (port 3001)
    npm run dev:frontend # Frontend (port 5173)

Development Workflow

Available Scripts

# Development
npm run dev              # Backend with nodemon
npm run dev:frontend     # Frontend with Vite HMR

# Building
npm run build            # Build frontend and server
npm run build:frontend   # Build React app
npm run build:server     # Compile TypeScript

# Testing
npm test                 # Run all tests
npm run test:cov         # Tests with coverage
npm run test:integration # Integration tests only

# Code Quality
npm run lint             # ESLint check
npm run lint:fix         # Auto-fix issues
npm run format:check     # Prettier check
npm run format           # Auto-format

# Docker
npm run docker:up        # Start containers
npm run docker:down      # Stop containers

Adding a New API Endpoint

  1. Create route handler in server/src/api/routes/v1/:
// server/src/api/routes/v1/my-feature.ts
import { Router } from 'express';
import { container } from '../../../config/container';

const router = Router();

router.get('/', async (req, res, next) => {
  try {
    const service = container.get('myService');
    const data = await service.getData();
    res.json({ ok: true, data });
  } catch (err) {
    next(err);
  }
});

export default router;
  1. Add business logic in server/src/services/:
// server/src/services/myService.ts
export class MyService {
  async getData() {
    // Business logic here
  }
}
  1. Register in container:
// server/src/config/container.ts
container.register('myService', new MyService());
  1. Mount route in server initialization

Adding a Frontend Component

  1. Create component:
// client/src/components/MyComponent.tsx
import React from 'react';

export const MyComponent: React.FC = () => {
  return <div className="p-4">My Component</div>;
};
  1. Add route in App.tsx:
import { lazy } from 'react';
const MyComponent = lazy(() => import('./components/MyComponent'));

<Route path="/my-route" element={<MyComponent />} />;
  1. Add navigation link in Navigation.tsx

Database Management

Common Operations

# Connect to database
docker exec -it shadowcheck_postgres psql -U shadowcheck_user -d shadowcheck_db

# Run migration
docker exec -i shadowcheck_postgres psql -U shadowcheck_user -d shadowcheck_db < sql/migrations/your_migration.sql

# Backup database
pg_dump -U shadowcheck_user -d shadowcheck_db -F c -f backup_$(date +%Y%m%d).dump

Useful Queries

-- Count networks by type
SELECT type, COUNT(*) FROM public.networks GROUP BY type;

-- Recent observations
SELECT * FROM public.observations
WHERE time >= EXTRACT(EPOCH FROM NOW() - INTERVAL '1 day') * 1000
LIMIT 10;

-- Tagged networks
SELECT bssid, tag_type, confidence FROM app.network_tags;

Testing

Run Tests

# All tests
npm test

# Specific test
npm test -- tests/unit/your-test.test.js

# With coverage
npm run test:cov

Writing Tests

// tests/api/dashboard-metrics.test.js
const request = require('supertest');
const app = require('../../server');

describe('GET /api/dashboard-metrics', () => {
  it('should return dashboard metrics', async () => {
    const response = await request(app).get('/api/dashboard-metrics').expect(200);

    expect(response.body).toHaveProperty('totalNetworks');
  });
});

Code Quality

Pre-commit Hooks

Husky runs automatically:

  • Secret scan
  • ESLint
  • Prettier

Commit Message Format

Follow Conventional Commits:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • test: Test additions
  • refactor: Code refactoring
  • chore: Maintenance tasks

Troubleshooting

Database Connection Errors

# Verify Docker PostgreSQL is running
docker ps | grep shadowcheck_postgres

# Test connection
docker exec shadowcheck_postgres psql -U shadowcheck_user -d shadowcheck_db

Port Already in Use

# Find process using port
lsof -i :3001

# Kill process
kill -9 <PID>

Memory Issues

# Increase Node.js heap size
NODE_OPTIONS="--max-old-space-size=4096" npm start

Related Documentation

Clone this wiki locally