From ded2b52425ce3c7b138f3dfc2ffe12d278932037 Mon Sep 17 00:00:00 2001 From: "Samuel Egbajie (MAJ0R)" <49847624+CodePapi@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:08:57 +0100 Subject: [PATCH 1/3] ft: added license --- .github/workflows/biome-check.yml | 31 +++ LICENSE | 22 +++ README.md | 122 ++++++++++++ backend/package.json | 6 +- backend/src/converter/converter.controller.ts | 4 +- backend/src/converter/converter.module.ts | 4 +- backend/src/converter/converter.service.ts | 32 +-- backend/src/main.ts | 2 +- backend/test/app.e2e-spec.ts | 2 +- biome.json | 54 +++++ docker-compose.yml | 4 +- frontend/README.md | 100 +++------- frontend/eslint.config.js | 23 --- frontend/index.html | 4 +- frontend/package-lock.json | 4 +- frontend/package.json | 4 +- frontend/public/codepapi.png | Bin 0 -> 1353 bytes frontend/src/App.css | 42 ---- frontend/src/App.tsx | 186 +++++++++++++----- frontend/src/assets/react.svg | 1 - frontend/src/components/LanguageSelector.tsx | 38 ++-- frontend/src/constants/languages.ts | 2 +- frontend/src/index.css | 2 +- package-lock.json | 179 +++++++++++++++++ package.json | 16 ++ 25 files changed, 652 insertions(+), 232 deletions(-) create mode 100644 .github/workflows/biome-check.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 biome.json delete mode 100644 frontend/eslint.config.js create mode 100644 frontend/public/codepapi.png delete mode 100644 frontend/src/App.css delete mode 100644 frontend/src/assets/react.svg create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/biome-check.yml b/.github/workflows/biome-check.yml new file mode 100644 index 0000000..5ab866a --- /dev/null +++ b/.github/workflows/biome-check.yml @@ -0,0 +1,31 @@ +name: Biome Lint and Format Check + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + biome_check: + runs-on: ubuntu-latest + + steps: + - name: ⬇️ Checkout Repository + uses: actions/checkout@v4 + + - name: βš™οΈ Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: πŸ“¦ Install Dependencies + run: npm install + + - name: πŸ“ Run Biome Lint Check + run: npm run biome:lint + + - name: πŸ“ Run Biome Format Check + run: npm run biome:format \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3081026 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2026 [Samuel Egbajie/CodePapi] + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b119bd3 --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +```markdown +# CodePapi AI ⚑ + +**CodePapi AI** is a professional, privacy-focused developer utility that brings the power of LLMs to your local workflow. Translate code from any language to another, migrate frameworks, reviews codes, and debug logicβ€”all without your data ever leaving your machine. + +![License](https://img.shields.io/badge/license-MIT-blue.svg) +![Ollama](https://img.shields.io/badge/AI-Ollama-orange.svg) +![React](https://img.shields.io/badge/Frontend-React-61DAFB.svg) +![NestJS](https://img.shields.io/badge/Backend-NestJS-E0234E.svg) +![Biome](https://img.shields.io/badge/Linter-Biome-60a5fa.svg) + +--- + +## πŸ“Ί Demo + +https://github.com/user-attachments/assets/00000000-0000-0000-0000-000000000000 + +--- + +## ✨ Features + +- πŸ”„ **Smart Translation**: Seamlessly convert code between 10+ languages (Go, Rust, Python, TS, etc., flexible enough to support more languages). +- πŸš€ **Migration Engine**: Expert-level presets for: + - React Class Components ➑️ Functional Components + - JavaScript ➑️ TypeScript + - CSS ➑️ Tailwind CSS + - React ➑️ Vue +- πŸ” **Deep Code Review**: AI-driven analysis of performance, security, and best practices. +- 🐞 **Interactive Bug Fixer**: Side-by-side **Diff View** highlighting exactly what the AI changed to fix your logic. +- πŸ”’ **Air-Gapped Privacy**: Powered by `phi3:mini` running locally via **Ollama**. + +--- + +## πŸš€ Quick Start + +### 1. Prerequisites +- [Docker & Docker Compose](https://docs.docker.com/get-docker/) + +### 2. Setup & Installation +```bash +# Clone the repository +git clone [https://github.com/yourusername/codepapi-ai.git](https://github.com/yourusername/codepapi-ai.git) +cd codepapi-ai + +# Start the entire stack (AI + Backend + Frontend) +docker-compose up -d + +``` + +### 3. Usage + +* **Frontend**: Open [http://localhost](https://www.google.com/search?q=http://localhost) +* **API**: Accessible at [http://localhost:3000](https://www.google.com/search?q=http://localhost:3000) + +*Note: The first startup pulls the Phi-3 Mini model (approx 2.3GB). Please ensure you have a stable internet connection.* + +--- + +## πŸ›  Tech Stack + +| Component | Technology | +| --- | --- | +| **AI Engine** | [Ollama](https://ollama.ai/) (phi3:mini) | +| **Orchestration** | LangChain.js | +| **Backend** | NestJS (Node.js) | +| **Frontend** | React, TailwindCSS, Lucide | +| **Editor** | Monaco Editor (VS Code Engine) | +| **Tooling** | Biome (Linting & Formatting) | + +--- + +## 🀝 Contributing + +We use **Biome** for lightning-fast linting and formatting. Please run the following before submitting a Pull Request: + +```bash +# Check and apply fixes +npx @biomejs/biome check --apply . + +``` + + **Adding Languages:** To add new programming languages or migration presets used by the UI, see the frontend documentation: `frontend/README.md` (section "Adding More Languages"). Edit `frontend/src/constants/languages.ts` to add entries. + +## πŸ“œ License + +Distributed under the MIT License. See `LICENSE` for more information. + +--- + +Created with ❀️ by [Your Name] + +``` + +--- + +### πŸ”§ Step 4: The Biome Configuration (`biome.json`) +Run `npx @biomejs/biome init` in your project root. It will create this file. Here is a solid configuration for your project: + +```json +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "noForeach": "off" + } + } + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 100 + } +} + +``` diff --git a/backend/package.json b/backend/package.json index 52a2b46..acf705c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,8 +1,8 @@ { - "name": "backend", + "name": "codepapi-ai-backend", + "description": "A backend for the CodePapi AI tool", + "author": "Samuel Egbajie", "version": "0.0.1", - "description": "", - "author": "", "private": true, "license": "UNLICENSED", "scripts": { diff --git a/backend/src/converter/converter.controller.ts b/backend/src/converter/converter.controller.ts index 47e3ec0..d0096b7 100644 --- a/backend/src/converter/converter.controller.ts +++ b/backend/src/converter/converter.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Post, Body } from '@nestjs/common'; +import { Body, Controller, Post } from '@nestjs/common'; import { ConverterService } from './converter.service'; @Controller('converter') @@ -19,4 +19,4 @@ export class ConverterController { async fix(@Body() data: { code: string; lang: string }) { return this.converterService.fixBugs(data.code, data.lang); } -} \ No newline at end of file +} diff --git a/backend/src/converter/converter.module.ts b/backend/src/converter/converter.module.ts index 09975fa..920a5b3 100644 --- a/backend/src/converter/converter.module.ts +++ b/backend/src/converter/converter.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { ConverterService } from './converter.service'; import { ConverterController } from './converter.controller'; +import { ConverterService } from './converter.service'; @Module({ providers: [ConverterService], - controllers: [ConverterController] + controllers: [ConverterController], }) export class ConverterModule {} diff --git a/backend/src/converter/converter.service.ts b/backend/src/converter/converter.service.ts index c1bff7d..171a87a 100644 --- a/backend/src/converter/converter.service.ts +++ b/backend/src/converter/converter.service.ts @@ -1,5 +1,5 @@ -import { Injectable, InternalServerErrorException } from '@nestjs/common'; import { ChatOllama } from '@langchain/ollama'; +import { Injectable, InternalServerErrorException } from '@nestjs/common'; @Injectable() export class ConverterService { @@ -8,25 +8,29 @@ export class ConverterService { constructor() { this.model = new ChatOllama({ baseUrl: process.env.OLLAMA_URL || 'http://localhost:11434', - model: 'qwen2.5-coder:1.5b', + model: 'phi3:mini', }); } // --- 1. CODE TRANSLATION --- -async convertCode(code: string, from: string, to: string) { - // Check if "to" is a migration preset - const isMigration = to.includes('-') || from.includes('-'); - - const prompt = ` + async convertCode(code: string, from: string, to: string) { + // Check if "to" is a migration preset + const isMigration = to.includes('-') || from.includes('-'); + + const prompt = ` You are an expert software architect specializing in ${isMigration ? 'code migration' : 'code translation'}. Task: Convert the input from ${from} to ${to}. - ${isMigration ? ` + ${ + isMigration + ? ` SPECIFIC INSTRUCTIONS FOR MIGRATION: - If moving from Class to Functional components, use React Hooks (useState, useEffect). - If moving to TypeScript, add proper interfaces and types. - If moving between frameworks (e.g., React to Vue), map lifecycle methods and state management accurately. - ` : ''} + ` + : '' + } RULES: - Return ONLY raw code. @@ -72,13 +76,13 @@ async convertCode(code: string, from: string, to: string) { private async executeInvoke(prompt: string, key: string) { try { const response = await this.model.invoke(prompt); - return { - success: true, - [key]: response.content + return { + success: true, + [key]: response.content, }; } catch (error) { - console.error(`AI Service Error:`, error); + console.error('AI Service Error:', error); throw new InternalServerErrorException('Failed to connect to AI engine'); } } -} \ No newline at end of file +} diff --git a/backend/src/main.ts b/backend/src/main.ts index b2895cf..4d34b3b 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -3,7 +3,7 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - app.enableCors(); + app.enableCors(); await app.listen(process.env.PORT ?? 3000); } bootstrap(); diff --git a/backend/test/app.e2e-spec.ts b/backend/test/app.e2e-spec.ts index 4df6580..99c63ec 100644 --- a/backend/test/app.e2e-spec.ts +++ b/backend/test/app.e2e-spec.ts @@ -1,5 +1,5 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; import * as request from 'supertest'; import { App } from 'supertest/types'; import { AppModule } from './../src/app.module'; diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..49cc8f1 --- /dev/null +++ b/biome.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false }, + "files": { + "include": ["src", "test"], + "ignoreUnknown": false, + "ignore": [ + "**/node_modules", + "dist/**" + ] + }, + "formatter": { + "enabled": true, + "useEditorconfig": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 80, + "attributePosition": "auto", + "bracketSpacing": true + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "useImportType": "off" + }, + "complexity": { + "noStaticOnlyClass": "off" + } + } + }, + "javascript": { + "parser": { + "unsafeParameterDecoratorsEnabled": true + }, + "formatter": { + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingCommas": "all", + "semicolons": "always", + "arrowParentheses": "always", + "bracketSameLine": false, + "quoteStyle": "single", + "attributePosition": "auto", + "bracketSpacing": true + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 4f93654..d27ecf2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: volumes: - ollama_data:/root/.ollama entrypoint: /bin/sh - command: -c "ollama serve & sleep 5 && ollama pull qwen2.5-coder:1.5b && wait" + command: -c "ollama serve & sleep 5 && ollama pull phi3:mini && wait" # 2. NestJS Backend backend: @@ -34,7 +34,7 @@ services: ports: - "80:80" depends_on: - - backend + - backend volumes: ollama_data: \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index d2e7761..847906c 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,73 +1,35 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## React Compiler - -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) +## Adding More Languages + +If you'd like to add new programming languages or framework migration presets to the UI, edit `frontend/src/constants/languages.ts`. The file exports two arrays: `LANGUAGES` (regular languages/options) and `MIGRATIONS` (framework-specific migration presets). Follow these guidelines: + +- File location: `frontend/src/constants/languages.ts` +- Each language entry should include at least `id` and `name`. +- Migration presets may include `id`, `name`, and any additional metadata your application uses. + +Example entries: + +```ts +// frontend/src/constants/languages.ts +export const LANGUAGES = [ + { id: 'javascript', name: 'JavaScript' }, + { id: 'typescript', name: 'TypeScript' }, + { id: 'python', name: 'Python' }, + // Add more languages here +]; + +export const MIGRATIONS = [ + { id: 'react-ts', name: 'React (Class) β†’ React (TS)' }, + { id: 'react-vue', name: 'React β†’ Vue' }, + // Add more migration presets here +]; ``` -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: +Tips: -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' +- Keep `id` values unique and use kebab-case (e.g. `react-ts`, `node-express`). +- If you add new migration presets, ensure the backend conversion logic (if any) recognizes the `id` and maps it to the proper prompt behavior. +- After editing `languages.ts`, the `LanguageSelector` and other UI components will automatically include your new items. +- You can add additional metadata (for example `editorMode`, `fileExtension`, or `isMigration`) if you want the UI or backend to handle the language differently β€” just update the consuming code accordingly. + +If you want help wiring up a more complex metadata format, tell me which fields you'd like and I can update the types and components for you. -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js deleted file mode 100644 index 5e6b472..0000000 --- a/frontend/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { defineConfig, globalIgnores } from 'eslint/config' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs.flat.recommended, - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]) diff --git a/frontend/index.html b/frontend/index.html index 70743a8..d2958bb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,9 +2,9 @@ - + - code-converter + codepapi ai
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8876beb..48f98fa 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "code-converter", + "name": "codepapi-ai-frontend", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "code-converter", + "name": "codepapi-ai-frontend", "version": "0.0.0", "dependencies": { "@monaco-editor/react": "^4.7.0", diff --git a/frontend/package.json b/frontend/package.json index 37cabcb..4220100 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,7 @@ { - "name": "code-converter", + "name": "codepapi-ai-frontend", + "description": "A frontend for the CodePapi AI tool", + "author": "Samuel Egbajie", "private": true, "version": "0.0.0", "type": "module", diff --git a/frontend/public/codepapi.png b/frontend/public/codepapi.png new file mode 100644 index 0000000000000000000000000000000000000000..69aa36581d37919c6150c5717ffc7d969f6d7375 GIT binary patch literal 1353 zcmV-P1-AN$P)2)@9Y-A(vq8ZG6c38Jf(m+A5kVp-;vp=05d^(>5kV18@giQ#NrHlS@uDDj zQI;G;6byohdr(lpRndbeBpzgwu-PP&$xQm`(AmjsI`vi8)X#K!*>C!{FsEO(f+S2?v5oiE9;S*^9HUJ$7I96{)U<1&RfMfM$1f~M8-ML=6H$N@C``(t` zBVWpOPprxO-osfOi5!P>Eoed;8qw;=?Lu|u5!jhuJP+;3KcsvAd(yu3S!wUMS6bbj zStqS5V*j^tEoed;8he>mV4~esofE*`-EYV>j~>dQxe5tgADC#zgG=9)0Cwi@%G0!c z`-?7pCs7v0)95Uh!6RO^9#jB3*;0jv zt+vrwFNaq=Yka5xc5iz@(^jp@XgwPNvTA3|R4Y0PGkC_ksi+ZPXV+tp2aDY|d zrJBA`09JXI<@JpZ3O2!loSTJ7pAmEf9^5x4!0>6PXqyGOXAb=d|37!uw%5Juwo z@wE5-0UT2r3*MLnZ@bpb`120%(ArQKi8noWR%`+o2(*aHs`Zit$nwX=P%L<8OcLOOcOp#}G2x*wNr2k)jSVkJfZFs; z0p2!%oS2131s<%DOJTm_A*?J?f``VW0GiU51$m663ZTj&DS%}nIS)J*qs)}nvkKr~V@-yCzF*c??at#B&l+PYfHbuE>zgt> z_A|S+4m{#jYf=r62Kzs}tXf=Bb{2z$GahZUTLBzw{3iX?=W7WuhnIQ7qc?ywd}e)B zPJg>xt8^x9@q{-#+Jw~zEE?u6ZGQ83EhZKw47}i}@Mp8F1hD9UhwZ7a_srxvk#!#0 z@lg1wvULJThfMdIKfNZKpWh+v)A)S4$#nuRy3pC zwR2~Hg#cFV{eM3dgpm>_zF3rvgS)fX6*+bbTF`_xG@`Z8?Yf;BKvyBNTE7A4c;^~` zS0F$~%hRpij6g@84ZsGVBLT { const isMigration = sourceLang.includes('-'); - + if (mode === 'translate') { if (isMigration) { // Auto-assign target language based on migration selection @@ -35,35 +44,49 @@ function App() { // Set presentable text when switching modes if (mode === 'review') { - setOutputCode('### AI Code Review\nSelect your input language and click "Run AI" to receive a deep analysis of your code quality, security, and performance.'); + setOutputCode( + '### AI Code Review\nSelect your input language and click "Run AI" to receive a deep analysis of your code quality, security, and performance.', + ); } else if (mode === 'fix') { setOutputCode(''); // Clear for Diff View } else if (mode === 'translate' && !targetLang) { setOutputCode(''); } - }, [sourceLang, mode]); + }, [sourceLang, mode, targetLang]); // --- Helpers --- const getEditorLanguage = (langId: string) => { if (!langId) return 'javascript'; - if (langId.includes('react') || langId.includes('vue') || langId.includes('javascript')) return 'typescript'; + if ( + langId.includes('react') || + langId.includes('vue') || + langId.includes('javascript') + ) + return 'typescript'; return langId; }; const stripCodeBlockFormatting = (code: string): string => { - return code.replace(/^```\w*\n/, '').replace(/\n```$/, '').trim(); + return code + .replace(/^```\w*\n/, '') + .replace(/\n```$/, '') + .trim(); }; const handleAction = async () => { if (!sourceCode.trim() || sourceCode === '// Your code here...') return; if (mode === 'translate' && !targetLang) { - alert("Please select a target language or framework migration."); + alert('Please select a target language or framework migration.'); return; } setIsProcessing(true); try { - let result; + let result: { + translatedCode?: string; + reviewContent?: string; + fixedCode?: string; + } | null = null; if (mode === 'translate') { result = await translateCode(sourceCode, sourceLang, targetLang); setOutputCode(stripCodeBlockFormatting(result.translatedCode)); @@ -75,80 +98,101 @@ function App() { setOutputCode(stripCodeBlockFormatting(result.fixedCode)); } } catch (error) { - console.error("API Error:", error); - alert("AI Engine is currently unavailable. Ensure Docker containers are running."); + console.error('API Error:', error); + alert( + 'AI Engine is currently unavailable. Ensure Docker containers are running.', + ); } finally { setIsProcessing(false); } }; return ( -
+
{/* Navbar */}
- {/* Input Panel */}
-
- +
@@ -158,7 +202,12 @@ function App() { language={getEditorLanguage(sourceLang)} value={sourceCode} onChange={(v) => setSourceCode(v || '')} - options={{ fontSize: 14, minimap: { enabled: false }, readOnly: isProcessing, padding: { top: 20 } }} + options={{ + fontSize: 14, + minimap: { enabled: false }, + readOnly: isProcessing, + padding: { top: 20 }, + }} />
@@ -166,30 +215,45 @@ function App() { {/* Output Panel / Diff View */}
-
+
{mode === 'translate' ? ( - ) : (
- +
+ AI Context +
- {mode === 'review' ? 'Analysis Mode' : 'Refactor Mode (Diff)'} + {mode === 'review' + ? 'Analysis Mode' + : 'Refactor Mode (Diff)'}
)}
-
@@ -201,7 +265,9 @@ function App() {
-

Select your target and click Run AI

+

+ Select your target and click Run AI +

)} @@ -210,23 +276,35 @@ function App() { height="100%" theme="vs-dark" original={sourceCode} - modified={isProcessing ? sourceCode : (outputCode || sourceCode)} + modified={ + isProcessing ? sourceCode : outputCode || sourceCode + } language={getEditorLanguage(sourceLang)} options={{ fontSize: 14, renderSideBySide: true, minimap: { enabled: false }, readOnly: true, - padding: { top: 20 } + padding: { top: 20 }, }} /> ) : ( )}
@@ -237,4 +315,4 @@ function App() { ); } -export default App; \ No newline at end of file +export default App; diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/components/LanguageSelector.tsx b/frontend/src/components/LanguageSelector.tsx index 2617fe2..2fa5bf5 100644 --- a/frontend/src/components/LanguageSelector.tsx +++ b/frontend/src/components/LanguageSelector.tsx @@ -5,33 +5,49 @@ interface Props { onChange: (val: string) => void; label: string; disabled?: boolean; - excludeId?: string; // Add this to filter out the left-side selection + excludeId?: string; + id?: string; } -export const LanguageSelector = ({ value, onChange, label, disabled, excludeId }: Props) => ( +export const LanguageSelector = ({ + value, + onChange, + label, + disabled, + excludeId, + id, +}: Props) => (
-
-); \ No newline at end of file +); diff --git a/frontend/src/constants/languages.ts b/frontend/src/constants/languages.ts index e93e275..16fe499 100644 --- a/frontend/src/constants/languages.ts +++ b/frontend/src/constants/languages.ts @@ -18,4 +18,4 @@ export const MIGRATIONS = [ { id: 'react-class-functional', name: 'React Class to Functional' }, { id: 'angular-react', name: 'Angular to React' }, { id: 'jquery-vanilla', name: 'jQuery to Vanilla JS' }, -]; \ No newline at end of file +]; diff --git a/frontend/src/index.css b/frontend/src/index.css index cb0ab94..6a1b540 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -7,4 +7,4 @@ body { .monaco-editor { padding-top: 8px; -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5389cf0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,179 @@ +{ + "name": "codepapi-ai", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "codepapi-ai", + "version": "1.0.0", + "devDependencies": { + "@biomejs/biome": "^1.5.3" + } + }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6d3b683 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "codepapi-ai", + "private": true, + "version": "1.0.0", + "scripts": { + "dev": "docker compose up", + "dev:build": "docker compose up --build", + "dev:down": "docker compose down", + "biome:format": "biome format --write .", + "biome:lint": "biome lint .", + "biome:fix": "biome check --apply ." + }, + "devDependencies": { + "@biomejs/biome": "^1.5.3" + } +} \ No newline at end of file From 26eb0c0bf795ca67515cbf355dc65f3d2dbae295 Mon Sep 17 00:00:00 2001 From: "Samuel Egbajie (MAJ0R)" <49847624+CodePapi@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:12:29 +0100 Subject: [PATCH 2/3] ft: added license --- biome.json | 5 +---- frontend/src/main.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/biome.json b/biome.json index 49cc8f1..2ea2178 100644 --- a/biome.json +++ b/biome.json @@ -4,10 +4,7 @@ "files": { "include": ["src", "test"], "ignoreUnknown": false, - "ignore": [ - "**/node_modules", - "dist/**" - ] + "ignore": ["**/node_modules", "dist/**", "frontend/src/main.tsx"] }, "formatter": { "enabled": true, diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index bef5202..2239905 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,10 +1,10 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import './index.css'; +import App from './App.tsx'; createRoot(document.getElementById('root')!).render( , -) +); From 8d892f2d4af419ec35330e6e10fbdbfab0d9583c Mon Sep 17 00:00:00 2001 From: "Samuel Egbajie (MAJ0R)" <49847624+CodePapi@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:14:30 +0100 Subject: [PATCH 3/3] ft: removed unused files --- frontend/public/vite.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 frontend/public/vite.svg diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file