Initialize Aidoit v0.1 monorepo
CI / frontend (push) Canceled after 0s
CI / api (push) Canceled after 0s

This commit is contained in:
Pavel Kerndl
2026-07-27 18:27:37 +02:00
commit c0b013f067
65 changed files with 1323 additions and 0 deletions
View File
View File
+20
View File
@@ -0,0 +1,20 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
aidoit_env: str = "development"
aidoit_admin_token: str = "replace-me"
database_url: str = "sqlite:///./aidoit.db"
redis_url: str = "redis://localhost:6379/0"
web_origin: str = "http://localhost:3000"
msp_origin: str = "http://localhost:3001"
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
)
settings = Settings()
+32
View File
@@ -0,0 +1,32 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.modules.health.router import router as health_router
from app.modules.projects.router import router as projects_router
app = FastAPI(
title="Aidoit API",
version="0.1.0",
description="Shared REST API for the Aidoit personal AI operating system.",
)
app.add_middleware(
CORSMiddleware,
allow_origins=[settings.web_origin, settings.msp_origin],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(health_router)
app.include_router(projects_router, prefix="/api/v1")
@app.get("/")
async def root() -> dict[str, str]:
return {
"name": "Aidoit API",
"version": "0.1.0",
"docs": "/docs",
}
View File
View File
+11
View File
@@ -0,0 +1,11 @@
from fastapi import APIRouter
router = APIRouter(tags=["health"])
@router.get("/health")
async def health() -> dict[str, str]:
return {
"status": "ok",
"service": "aidoit-api",
}
+28
View File
@@ -0,0 +1,28 @@
from fastapi import APIRouter, HTTPException, status
from app.modules.projects.schemas import ProjectCreate, ProjectRead
from app.modules.projects.service import project_service
router = APIRouter(prefix="/projects", tags=["projects"])
@router.get("", response_model=list[ProjectRead])
async def list_projects() -> list[ProjectRead]:
return project_service.list()
@router.post(
"",
response_model=ProjectRead,
status_code=status.HTTP_201_CREATED,
)
async def create_project(payload: ProjectCreate) -> ProjectRead:
return project_service.create(payload)
@router.get("/{project_id}", response_model=ProjectRead)
async def get_project(project_id: int) -> ProjectRead:
project = project_service.get(project_id)
if project is None:
raise HTTPException(status_code=404, detail="Project not found")
return project
+19
View File
@@ -0,0 +1,19 @@
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
ProductType = Literal["web", "desktop", "msp"]
class ProjectCreate(BaseModel):
name: str = Field(min_length=1, max_length=120)
description: str = Field(default="", max_length=2000)
product: ProductType = "web"
class ProjectRead(ProjectCreate):
model_config = ConfigDict(from_attributes=True)
id: int
created_at: datetime
+31
View File
@@ -0,0 +1,31 @@
from datetime import UTC, datetime
from itertools import count
from app.modules.projects.schemas import ProjectCreate, ProjectRead
class ProjectService:
def __init__(self) -> None:
self._ids = count(1)
self._projects: list[ProjectRead] = []
def list(self) -> list[ProjectRead]:
return self._projects.copy()
def create(self, payload: ProjectCreate) -> ProjectRead:
project = ProjectRead(
id=next(self._ids),
created_at=datetime.now(UTC),
**payload.model_dump(),
)
self._projects.append(project)
return project
def get(self, project_id: int) -> ProjectRead | None:
return next(
(project for project in self._projects if project.id == project_id),
None,
)
project_service = ProjectService()
View File
View File
View File
View File