Skip to content

kryzhanovskyik/Codeess

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Codeess

A visual block-based programming platform. Users build programs by connecting blocks in the browser — blocks are serialized to AST-JSON, stored in a database, and executed by a custom interpreter on the backend.


Table of Contents


Architecture

Browser (Next.js)
    │  REST API (JSON)
    ▼
FastAPI  (backend)
    │  enqueue task
    ▼
Celery Worker ──► AST Interpreter
    │
    ├─► PostgreSQL  (projects, modules, runs, schedules)
    └─► Redis       (Celery broker + response cache)

Celery Beat checks schedules every minute and automatically enqueues runs.


Quick Start (one command)

Requirements: Docker Desktop — that's it. No Python, no Node.js, no database setup needed.

# 1. Clone the repository
git clone <repo-url>
cd Codeess-project

# 2. Start everything
docker compose up --build

That single docker compose up --build command will:

  • Start a PostgreSQL database
  • Start a Redis instance
  • Apply all database migrations automatically
  • Start the FastAPI backend on http://localhost:8000
  • Start the Celery worker (executes programs in the background)
  • Start the Celery beat scheduler (for scheduled runs)
  • Start the Next.js frontend on http://localhost:3000

Open http://localhost:3000 in your browser — the app is ready.

To stop everything: docker compose down
To also delete the database data: docker compose down -v


Backend

Tech Stack

Technology Role
Python 3.12 Language
FastAPI HTTP framework
SQLAlchemy 2 (async) + asyncpg ORM + PostgreSQL driver
Alembic Database migrations
Celery 5 + Redis Task queue (worker + beat scheduler)
Pydantic v2 + pydantic-settings Validation, schemas, configuration
PyJWT + passlib[bcrypt] Authentication (JWT in httponly cookie)
fastapi-cache + Redis Response caching
Poetry Dependency management
Docker Containerization

Project Structure

codeess-backend/
├── src/
│   ├── main.py              # FastAPI entry point, routers, CORS middleware
│   ├── config.py            # Settings via pydantic-settings (.env)
│   ├── database.py          # SQLAlchemy engines and session factory
│   ├── cache.py             # Redis cache wrapper
│   ├── exceptions.py        # Domain exceptions
│   │
│   ├── api/                 # HTTP routers (FastAPI)
│   │   ├── auth.py          # /auth — register, login, logout, /me
│   │   ├── projects.py      # /projects — CRUD
│   │   ├── modules.py       # /projects/{id}/modules — CRUD
│   │   ├── runs.py          # /modules/{id}/runs — execute and view runs
│   │   ├── schedules.py     # /schedules — scheduled runs
│   │   ├── dependencies.py  # Dependency injection: DB session, UserID, validation
│   │   └── exceptions.py    # HTTP exceptions
│   │
│   ├── services/            # Business logic layer
│   ├── repositories/        # Database access layer (Repository + Unit of Work pattern)
│   │   └── mappers/         # ORM model → domain entity mapping
│   ├── models/              # SQLAlchemy ORM models
│   ├── schemas/             # Pydantic schemas (requests / responses)
│   │
│   ├── logic/               # Interpreter core
│   │   ├── ast/
│   │   │   ├── base.py        # Abstract classes: ASTNode, Expression, Statement
│   │   │   ├── expressions.py # Literals, variables, operators, function calls, ...
│   │   │   ├── statements.py  # Assign, If, While, For, FunctionDef, ClassDef, Import, ...
│   │   │   ├── program.py     # Program — root node, creates and runs Runtime
│   │   │   └── exceptions.py  # BreakSignal, ContinueSignal, ReturnSignal
│   │   ├── parser/
│   │   │   └── factory.py     # AST-JSON → object tree deserialization
│   │   ├── runtime/
│   │   │   └── runtime.py     # Execution environment: scope stack, built-ins, I/O
│   │   └── interpreter/
│   │       └── runner.py      # run_from_json() — interpreter entry point
│   │
│   └── tasks/               # Celery tasks
│       ├── celery_app.py    # Celery instance, beat schedule
│       ├── runs.py          # run_module_task: execute a module by run_id
│       └── schedules.py     # check_and_fire: trigger due scheduled runs
│
├── migrations/              # Alembic migrations
├── docker-compose.yml       # Backend-only compose (legacy)
├── Dockerfile
└── pyproject.toml

Domain Entities

User
 └── Project (1..*)
      └── Module (1..*) — stores ast_json (the program as AST-JSON)
           ├── Run (1..*) — execution record (pending → running → done/failed)
           └── ScheduledRun (0..*) — automatic run schedule

Run fields:

  • input_json — inputs passed at run time
  • output_json — output lines { "output": [...] }
  • errors — error message on failure
  • statuspending | running | done | failed
  • created_at, finished_at

ScheduledRun supports types: hourly, daily, weekly with configurable hour, minute, and weekday.

API Reference

Method Path Description
POST /auth/register Register a new user
POST /auth/login Login (sets httponly JWT cookie)
POST /auth/logout Logout
GET /auth/me Current user
GET /projects List user's projects
POST /projects Create a project
PUT / PATCH / DELETE /projects/{id} Update / delete a project
GET /projects/{id}/modules List modules in a project
POST /projects/{id}/modules Create a module
PUT / PATCH / DELETE /modules/{id} Update / delete a module
GET /modules/{id}/runs Run history for a module
POST /modules/{id}/runs Execute a module
GET /modules/{id}/runs/{run_id} Run status / result
POST /schedules Create a schedule
GET /schedules/module/{module_id} Schedules for a module
PATCH / DELETE /schedules/{id} Update / delete a schedule

Interactive API docs (Swagger UI): http://localhost:8000/docs

Interpreter Logic

The core feature of the project — a custom interpreter that executes programs represented as AST-JSON.

Full path from block to output:

1. User assembles a program from blocks in the frontend
2. Frontend serializes blocks to AST-JSON and saves to module (PATCH /modules/{id})
3. POST /modules/{id}/runs { inputs: [...] }
   → service creates a Run record with status "pending"
   → calls run_module_task.delay(run_id)            # async Celery task
4. Celery worker:
   a) Loads ast_json from DB (Redis cache, TTL 2 min)
   b) Loads ast_json of all other modules in the project (for inter-module imports)
   c) Sets status = "running"
   d) factory.build_statement(node) for each node → AST object tree
   e) Program(body).run(inputs, project_modules) → Runtime
   f) Saves output to run.output_json, status = "done"
      On exception → status = "failed", run.errors = str(e)
5. GET /modules/{id}/runs/{run_id} returns result (Redis cache, TTL 24 h)

Runtime (src/logic/runtime/runtime.py):

  • Scope stack (push_scope / pop_scope) — variable isolation inside blocks, functions, loops
  • Input queue _inputs — simulates input() from a pre-supplied list
  • Output buffer output: list[str] — collects print() results
  • Built-in functions: len, range, str, int, float, sum, min, max, abs, input, print
  • System module imports (whitelist: math, random, statistics, itertools, etc.)
  • Inter-module imports within a project — sibling module runs in an isolated sub-Runtime, its global names are exported
  • Infinite loop protection: 10 000 iteration limit per loop, 1 000 000 global step limit

Supported language constructs:

Category Constructs
Expressions Literals, variables, arithmetic (+−×÷%), comparisons, and/or/not, ternary, function calls, lambda, attribute access, indexing
Collections list, dict, set, tuple literals; index access, index assignment
Statements assign, print, if/elif/else, while, for range, for each, repeat N times, break, continue, return, raise
Functions Definition (def), recursion, instance methods (self)
Classes class, instances (new), attributes, methods
Error handling try/except with exception type matching
Imports Whitelisted system modules, project module imports
Utilities json_parse, json_stringify, csv_parse, http_get, http_post (external URLs only)

Background Tasks (Celery)

Three independent services:

  • codeess_back — FastAPI, handles HTTP requests
  • codeess_celery_worker — consumes tasks from the queue (module execution)
  • codeess_celery_beat — scheduler, calls schedules.check_and_fire every minute, which finds due schedules, creates Run records, and enqueues tasks

Caching (Redis)

Redis uses two databases:

DB Purpose TTL
REDIS_CELERY_DB (0) Celery broker and backend
REDIS_CACHE_DB (1) API response cache 10 min (/auth/me), 2 min (module AST), 24 h (completed Run)

Configuration

Settings are read from the .env file at the project root (copied from .env.example):

MODE=LOCAL          # TEST | LOCAL | DEV | PROD

DB_HOST=postgres    # use "localhost" when running without Docker
DB_PORT=5432
DB_USER=codeess
DB_PASS=codeess
DB_NAME=codeess

REDIS_HOST=redis    # use "localhost" when running without Docker
REDIS_PORT=6379
REDIS_CELERY_DB=0
REDIS_CACHE_DB=1

JWT_SECRET_KEY=change-me-to-a-long-random-string
JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=60

ALLOWED_ORIGINS=["http://localhost:3000"]

When MODE=PROD the JWT cookie is set with the Secure flag (HTTPS only).


Frontend

codeess-frontend — Next.js 16 / React 19 / TypeScript / TailwindCSS. A visual block code editor with a drag-and-drop interface. Blocks are serialized to AST-JSON and sent to the backend. Supports authentication, project and module management, run history, and schedule configuration.


Running Without Docker

If Docker is not available, each service can be run manually.

Backend

cd codeess-backend

# Install dependencies
poetry install
codeess-backend  codeess-frontend  docker-compose.yml  README.md  venv
(codeess-backend-py3.12) kiripupsik5@kiripupsik5-ROG-Strix-G531GU:~/Projects/Programming/Python/Codeess/Codeess-project$ docker compose up --build
env file /home/kiripupsik5/Projects/Programming/Python/Codeess/Codeess-project/.env not found: stat /home/kiripupsik5/Projects/Programming/Python/Codeess/Codeess-project/.env: no such file or directory
(codeess-backend-py3.12) kiripupsik5@kiripupsik5-ROG-Strix-G531GU:~/Projects/Programming/Python/Codeess/Codeess-project$ ls
codeess-backend  codeess-frontend  docker-compose.yml  README.md  venv
(codeess-backend-py3.12) kiripupsik5@kiripupsik5-ROG-Strix-G531GU:~/Projects/Programming/Python/Codeess/Codeess-project$ 
# Copy and edit the env file
cp ../.env.example .env-local
# Edit .env-local: set DB_HOST=localhost, REDIS_HOST=localhost

# Apply database migrations
poetry run alembic upgrade head

# Start FastAPI
poetry run uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload

# In a separate terminal — Celery worker
poetry run celery --app=src.tasks.celery_app:celery_instance worker -l INFO

# In a separate terminal — Celery beat (for schedules)
poetry run celery --app=src.tasks.celery_app:celery_instance beat -l INFO --scheduler celery.beat:PersistentScheduler

PostgreSQL and Redis must be running locally before starting the backend.

Frontend

cd codeess-frontend

npm install
npm run dev
# Open http://localhost:3000

Database Migrations

cd codeess-backend

# Apply all pending migrations
poetry run alembic upgrade head

# Create a new migration after changing models
poetry run alembic revision --autogenerate -m "description"

# Roll back the last migration
poetry run alembic downgrade -1

About

Visual programming language with a custom Python-based interpreter and AST schema engine. Built from scratch — lexer, parser, tree-walker, and execution runtime.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors