Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .tmuxinator/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: codefox
root: <%= ENV["PWD"] %>

on_project_start: tmux set-option -g prefix C-a

windows:
- backend:
root: <%= ENV["PWD"] %>/backend
panes:
- backend:
- echo "Backend Server (Ctrl+a 1 to focus, Ctrl+a r to restart)"
- pnpm dev
- frontend:
root: <%= ENV["PWD"] %>/frontend
layout: main-vertical
panes:
- frontend:
- echo "Frontend Server (Ctrl+a 2 to focus, Ctrl+a r to restart)"
- pnpm dev
- codegen:
- echo "Codegen Watch (Ctrl+a 2 to focus, Ctrl+a r to restart)"
- pnpm generate:watch
- llm:
root: <%= ENV["PWD"] %>/llm-server
panes:
- llm:
- echo "LLM Server (Ctrl+a 3 to focus, Ctrl+a r to restart)"
- pnpm dev
122 changes: 122 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,125 @@ graph TD
classDef layerStyle fill:#f4f4f4,stroke:#666,stroke-width:1px,stroke-dasharray: 5 5
class Project_Generate_Layer layerStyle
```

# CodeFox Development Guide

## Prerequisites

Before you begin, ensure you have the following installed:

- Node.js >= 18.0.0
- PNPM 9.1.2 (`npm install -g pnpm@9.1.2`)
- Tmux >= 3.2
- Tmuxinator >= 3.0.0 (`gem install tmuxinator`)

## Project Structure

The project consists of three main components:

```
codefox/
├── backend/ # NestJS backend server
├── frontend/ # Next.js frontend application
└── llm-server/ # LLM service
```

## Installation

1. Clone the repository:

```bash
git clone <repository-url>
cd codefox
```

2. Install dependencies:

```bash
pnpm install
```

3. Set up environment variables:

```bash
# Copy and configure environment files for each service
cp backend/.env.template backend/.env
cp frontend/.env.template frontend/.env
cp llm-server/.env.template llm-server/.env
```

## Development

### Using Tmuxinator (Recommended)

The project includes a Tmuxinator configuration for easy development. This will start all services in separate windows with proper layouts:

```bash
pnpm dev:tmux
```

This command will create:

- Window 1: Backend server
- Window 2: Frontend development server (left) and GraphQL codegen watcher (right)
- Window 3: LLM server

Tmux Navigation:

- `Ctrl+a 1/2/3` - Switch between windows
- `Ctrl+a r` - Restart current pane's service
- `Ctrl+a d` - Detach from session

### Manual Development

If you prefer to run services individually:

```bash
# Start all services
pnpm dev

# Or start services individually
pnpm dev:backend # Start backend only
cd frontend && pnpm dev # Start frontend only
cd llm-server && pnpm dev # Start LLM server only
```

## Additional Commands

```bash
pnpm build # Build all packages
pnpm lint # Run linting
pnpm format # Format code
pnpm test # Run tests
```

## GraphQL Code Generation

The frontend uses GraphQL with automatic type generation. The codegen watcher is automatically started in the Tmuxinator setup, but you can also run it manually:

```bash
cd frontend
pnpm generate:watch
```

## Troubleshooting

If you encounter any issues:

1. Ensure all environment variables are properly set
2. Check if all required services are running
3. Clear node_modules and reinstall dependencies:

```bash
pnpm clean
pnpm install
```

4. For Tmuxinator issues:
- Ensure Tmux is running version 3.2 or higher
- Check if the session is already running: `tmux ls`
- Kill existing session if needed: `tmux kill-session -t codefox`

## License

ISC
2 changes: 1 addition & 1 deletion backend/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
PORT=8080
JWT_SECRET="JACKSONCHENNAHEULALLEN"
SALT_ROUNDS=123
SALT_ROUNDS=123
3 changes: 2 additions & 1 deletion backend/.env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
PORT=8080
JWT_SECRET="JACKSONCHENNAHEULALLEN"
SALT_ROUNDS=123
SALT_ROUNDS=123
OPENAI_BASE_URI="http://localhost:3001"
1 change: 1 addition & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ lerna-debug.log*

# OS
.DS_Store
*.db

# Tests
/coverage
Expand Down
Binary file added backend/database.db
Binary file not shown.
17 changes: 16 additions & 1 deletion backend/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: 'src',
testRegex: '.*\\.spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
'^.+\\.(t|j)s$': [
'ts-jest',
{
tsconfig: {
allowJs: true,
module: 'ESNext',
},
useESM: true,
},
],
},
collectCoverageFrom: ['**/*.(t|j)s'],
coverageDirectory: '../coverage',
testEnvironment: 'node',
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/$1',
'^(\\.{1,2}/.*)\\.js$': '$1',
},
modulePaths: ['<rootDir>'],
moduleDirectories: ['node_modules', 'src'],
testPathIgnorePatterns: ['/template'],
transformIgnorePatterns: [
'node_modules/(?!(strip-json-comments|other-esm-packages)/)',
],
preset: 'ts-jest/presets/default-esm',
};
13 changes: 8 additions & 5 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
"license": "UNLICENSED",
"packageManager": "pnpm@9.1.0",
"scripts": {
"build": "nest build",
"build": "pnpm run build:common && nest build",
"build:common": "pnpm --filter codefox-common run build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "ts-prune \"{src,apps,libs,test}/**/*.ts\" && eslint \"{src,apps,libs,test}/**/*.ts\" --fix ",
"start": "nest start --watch",
"start:dev": "nest start --watch",
"dev": "pnpm start:dev",
"start:dev": "NODE_OPTIONS=\"--experimental-specifier-resolution=node\" nest start --watch",
"dev": "pnpm run build:common && pnpm start:dev",
"dev:backend": "pnpm start:dev",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start:prod": "node --experimental-specifier-resolution=node dist/main",
"test": "jest --passWithNoTests",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
Expand Down Expand Up @@ -55,6 +56,7 @@
"markdown-to-txt": "^2.0.1",
"normalize-path": "^3.0.0",
"openai": "^4.77.0",
"p-queue-es5": "^6.0.2",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"sqlite3": "^5.1.7",
Expand All @@ -74,6 +76,7 @@
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"codefox-common": "workspace:*",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
Expand All @@ -89,4 +92,4 @@
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
}
}
}
4 changes: 1 addition & 3 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { ProjectModule } from './project/project.module';
import { TokenModule } from './token/token.module';
import { UserModule } from './user/user.module';
import { InitModule } from './init/init.module';
import { RolesGuard } from './guard/roles.guard';
import { MenuGuard } from './guard/menu.guard';
import { User } from './user/user.model';
import { AppResolver } from './app.resolver';
import { APP_INTERCEPTOR } from '@nestjs/core';
Expand All @@ -33,7 +31,7 @@ import { LoggingInterceptor } from 'src/interceptor/LoggingInterceptor';
}),
TypeOrmModule.forRoot({
type: 'sqlite',
database: join(process.cwd(), 'src/database.sqlite'),
database: join(process.cwd(), './database.db'),
synchronize: true,
entities: [__dirname + '/**/*.model{.ts,.js}'],
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import * as path from 'path';
import * as os from 'os';
import { existsSync, rmdirSync } from 'fs-extra';

Check warning on line 3 in backend/src/build-system/__tests__/test-file-create-and-path.spec.ts

View workflow job for this annotation

GitHub Actions / autofix

'rmdirSync' is defined but never used. Allowed unused vars must match /^_/u
import * as pathUtil from '../../config/common-path';
import { saveGeneratedCode } from 'src/build-system/utils/files';
import {
getRootDir,
getProjectsDir,
getProjectPath,
} from 'src/config/common-path';
import { getProjectPath, getProjectsDir, getRootDir } from 'codefox-common';

describe('Path Utilities', () => {
const APP_NAME = 'codefox';
Expand Down Expand Up @@ -47,14 +42,14 @@
});

it('should resolve paths correctly', () => {
const rootDir = pathUtil.getRootDir();
const projectsDir = pathUtil.getProjectsDir();
const rootDir = getRootDir();
const projectsDir = getProjectsDir();
expect(rootDir).toBeDefined();
expect(projectsDir).toBeDefined();
});

it('should create and return the root directory', async () => {
const rootDir = pathUtil.getRootDir();
const rootDir = getRootDir();

await generateAndSaveCode();
expect(rootDir).toBe(ROOT_DIR);
Expand All @@ -79,8 +74,8 @@

try {
const filePath = await saveGeneratedCode(fileName, generatedCode);
console.log(`Generated code saved at: ${filePath}`);

Check warning on line 77 in backend/src/build-system/__tests__/test-file-create-and-path.spec.ts

View workflow job for this annotation

GitHub Actions / autofix

Unexpected console statement
} catch (error) {
console.error('Failed to save generated code:', error);

Check warning on line 79 in backend/src/build-system/__tests__/test-file-create-and-path.spec.ts

View workflow job for this annotation

GitHub Actions / autofix

Unexpected console statement
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { copyProjectTemplate } from 'src/build-system/utils/files';
import { promises as fs } from 'fs';
import { v4 as uuidv4 } from 'uuid';
import { getTemplatePath } from 'src/config/common-path';
import { Logger } from '@nestjs/common';
import { getTemplatePath } from 'codefox-common';

describe('Copy Project Template', () => {
it('should copy the template to the specified UUID folder', async () => {
Expand Down
84 changes: 84 additions & 0 deletions backend/src/build-system/__tests__/test.sms-lvl2.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { BuildSequence } from '../types';
import { executeBuildSequence, objectToMarkdown, writeToFile } from './utils';

describe('Build Sequence Test', () => {
it('should execute build sequence successfully', async () => {
const sequence: BuildSequence = {
id: 'test-backend-sequence',
version: '1.0.0',
name: 'Spotify-like Music Web',
description: 'Users can play music',
databaseType: 'SQLite',
steps: [
{
id: 'step-0',
name: 'Project Initialization',
parallel: false,
nodes: [
{
id: 'op:PROJECT::STATE:SETUP',
name: 'Project Folders Setup',
},
],
},
{
id: 'step-1',
name: 'Initial Analysis',
parallel: false,
nodes: [
{
id: 'op:PRD',
name: 'Project Requirements Document Node',
},
],
},
{
id: 'step-2',
name: 'UX Base Document Generation',
parallel: false,
nodes: [
{
id: 'op:UX:SMD',
name: 'UX Sitemap Document Node',
requires: ['op:PRD'],
},
],
},
{
id: 'step-3',
name: 'Parallel UX Processing',
parallel: true,
nodes: [
{
id: 'op:UX:SMS',
name: 'UX Sitemap Structure Node',
requires: ['op:UX:SMD'],
},
{
id: 'op:UX:DATAMAP:DOC',
name: 'UX DataMap Document Node',
requires: ['op:UX:SMD'],
},
],
},
{
id: 'step-4',
name: 'Parallel Project Structure',
parallel: true,
nodes: [
{
id: 'op:UX:SMS:LEVEL2',
name: 'Level 2 UX Sitemap Structure Node details',
requires: ['op:UX:SMS'],
},
],
},
],
};

const result = await executeBuildSequence('fullstack-code-gen', sequence);
expect(result.success).toBe(true);
expect(result.metrics).toBeDefined();
console.log(`Logs saved to: ${result.logFolderPath}`);
}, 300000);
});
Loading
Loading