diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy_astro.yml similarity index 100% rename from .forgejo/workflows/deploy.yml rename to .forgejo/workflows/deploy_astro.yml diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..a2017a4 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,7 @@ +# Database + +MySQL is used. + +CREATE DATABASE noxiosdb; +CREATE USER 'noxios'@'localhost'; +GRANT ALL PRIVILEGES ON noxiosdb.* To 'noxios'@'localhost' IDENTIFIED BY 'password'; diff --git a/backend/__pycache__/config.cpython-312.pyc b/backend/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..edc991b Binary files /dev/null and b/backend/__pycache__/config.cpython-312.pyc differ diff --git a/backend/__pycache__/database.cpython-312.pyc b/backend/__pycache__/database.cpython-312.pyc new file mode 100644 index 0000000..ad28066 Binary files /dev/null and b/backend/__pycache__/database.cpython-312.pyc differ diff --git a/backend/__pycache__/main.cpython-312.pyc b/backend/__pycache__/main.cpython-312.pyc index 1c68689..dcee18b 100644 Binary files a/backend/__pycache__/main.cpython-312.pyc and b/backend/__pycache__/main.cpython-312.pyc differ diff --git a/backend/__pycache__/models.cpython-312.pyc b/backend/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000..d1097fa Binary files /dev/null and b/backend/__pycache__/models.cpython-312.pyc differ diff --git a/backend/__pycache__/user.cpython-312.pyc b/backend/__pycache__/user.cpython-312.pyc new file mode 100644 index 0000000..c0a33c1 Binary files /dev/null and b/backend/__pycache__/user.cpython-312.pyc differ diff --git a/backend/config.py b/backend/config.py new file mode 100644 index 0000000..3bf6b86 --- /dev/null +++ b/backend/config.py @@ -0,0 +1 @@ +DATABASE_URL = 'mysql+aiomysql://noxios:@127.0.0.1:3306/nexiosdb' \ No newline at end of file diff --git a/backend/controller/__pycache__/comments.cpython-312.pyc b/backend/controller/__pycache__/comments.cpython-312.pyc new file mode 100644 index 0000000..b087b28 Binary files /dev/null and b/backend/controller/__pycache__/comments.cpython-312.pyc differ diff --git a/backend/controller/__pycache__/newsletter.cpython-312.pyc b/backend/controller/__pycache__/newsletter.cpython-312.pyc new file mode 100644 index 0000000..36197e6 Binary files /dev/null and b/backend/controller/__pycache__/newsletter.cpython-312.pyc differ diff --git a/backend/controller/__pycache__/user.cpython-312.pyc b/backend/controller/__pycache__/user.cpython-312.pyc new file mode 100644 index 0000000..937e33d Binary files /dev/null and b/backend/controller/__pycache__/user.cpython-312.pyc differ diff --git a/backend/controller/comments.py b/backend/controller/comments.py index e69de29..839b7b9 100644 --- a/backend/controller/comments.py +++ b/backend/controller/comments.py @@ -0,0 +1,7 @@ +def setup_comment_routes(app): + + #get comments + @app.get("/comment/{id}") + async def get_comments_for_post(req, res): + return res.json(status_code=201) + #add comment \ No newline at end of file diff --git a/backend/controller/newsletter.py b/backend/controller/newsletter.py index e69de29..709df5e 100644 --- a/backend/controller/newsletter.py +++ b/backend/controller/newsletter.py @@ -0,0 +1,12 @@ + +def setup_newsletter_routes(app): + + # Create Mail Entry by Mail + @app.post("/newsletter") + async def create_mail_entry(request, response): + return response.json(status_code=201) + + # Delete Mail Entry by UUID + @app.put("/newsletter/{id}") + async def create_mail_entry(request, response): + return response.json(status_code=201) \ No newline at end of file diff --git a/backend/controller/user.py b/backend/controller/user.py new file mode 100644 index 0000000..2b030eb --- /dev/null +++ b/backend/controller/user.py @@ -0,0 +1,29 @@ +from database import get_db +from nexios import Depend +from nexios.http import Request, Response +from sqlalchemy.ext.asyncio import AsyncSession +from models import User + +def setup_user_routes(app): + + @app.get("/users") + async def list_users( + request: Request, + response: Response, + db: AsyncSession = Depend(get_db) + ): + result = await db.execute("SELECT * FROM users") + users = result.fetchall() + return response.json(users) + + @app.post("/users") + async def create_user( + request: Request, + response: Response, + db: AsyncSession = Depend(get_db) + ): + data = await request.json + user = User(**data) + db.add(user) + await db.commit() + return response.json({"id": user.id}) \ No newline at end of file diff --git a/backend/database.py b/backend/database.py new file mode 100644 index 0000000..20b4a49 --- /dev/null +++ b/backend/database.py @@ -0,0 +1,29 @@ +from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession +from sqlalchemy.orm import declarative_base +from config import DATABASE_URL + +engine = create_async_engine( + DATABASE_URL, + echo=True, + pool_size=5, + max_overflow=10, +) + +AsyncSessionLocal = async_sessionmaker( + engine, + class_=AsyncSession, + expire_on_commit=False, +) + +Base = declarative_base() + +async def init_db(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + +async def get_db() -> AsyncSession: + async with AsyncSessionLocal() as session: + try: + yield session + finally: + await session.close() \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 7537112..16c7c75 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,20 +1,20 @@ +from database import init_db +from controller.user import setup_user_routes +from controller.comments import setup_comment_routes +from controller.newsletter import setup_newsletter_routes from nexios import NexiosApp import uvicorn -# Create a new Nexios application + app = NexiosApp() -# Define a simple route -@app.get("/") -async def hello_world(request, response): - return response.json({ - "message": "Hello from Nexios!", - "status": "success" - }) +@app.on_startup +async def startup(): + await init_db() -# If you forget to use async def for your handler, Nexios will run the handler in a threadpool - -# If you define two routes with the same path and method, Nexios will raise a conflict error at startup. +setup_newsletter_routes(app) +setup_comment_routes(app) +setup_user_routes(app) # Run the application if __name__ == "__main__": diff --git a/backend/models.py b/backend/models.py new file mode 100644 index 0000000..6f57b7c --- /dev/null +++ b/backend/models.py @@ -0,0 +1,14 @@ +from sqlalchemy import Column, Integer, String, Boolean, DateTime +from sqlalchemy.orm import declarative_base +from datetime import datetime + +Base = declarative_base() + +class User(Base): + __tablename__ = "users" + + id = Column(Integer, primary_key=True) + name = Column(String(100)) + email = Column(String(100), unique=True) + is_active = Column(Boolean, default=True) + created_at = Column(DateTime, default=datetime.now) \ No newline at end of file diff --git a/backend/pyrefly.toml b/backend/pyrefly.toml new file mode 100644 index 0000000..3bff0ea --- /dev/null +++ b/backend/pyrefly.toml @@ -0,0 +1,6 @@ +project-includes = [ + "venv/**/*.py*", + "venv/**/*.ipynb", +] + +python-platform = "linux" \ No newline at end of file diff --git a/backend/user.py b/backend/user.py new file mode 100644 index 0000000..590b9f0 --- /dev/null +++ b/backend/user.py @@ -0,0 +1,17 @@ +from nexios.pagination import SyncDataHandler +from sqlalchemy import select +from models import User + +class UserDataHandler(SyncDataHandler): + def __init__(self, session): + self.session = session + + def get_total_items(self): + result = self.session.execute(select(User)) + return len(result.scalars().all()) + + def get_items(self, offset, limit): + result = self.session.execute( + select(User).offset(offset).limit(limit) + ) + return result.scalars().all() \ No newline at end of file diff --git a/backend/venv/bin/pyrefly b/backend/venv/bin/pyrefly new file mode 100755 index 0000000..ad62c98 Binary files /dev/null and b/backend/venv/bin/pyrefly differ diff --git a/backend/venv/bin/tortoise b/backend/venv/bin/tortoise new file mode 100755 index 0000000..466af28 --- /dev/null +++ b/backend/venv/bin/tortoise @@ -0,0 +1,8 @@ +#!/home/ebby/Desktop/Bluewaterblog/backend/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from tortoise.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/venv/include/site/python3.12/greenlet/greenlet.h b/backend/venv/include/site/python3.12/greenlet/greenlet.h new file mode 100644 index 0000000..d02a16e --- /dev/null +++ b/backend/venv/include/site/python3.12/greenlet/greenlet.h @@ -0,0 +1,164 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */ + +/* Greenlet object interface */ + +#ifndef Py_GREENLETOBJECT_H +#define Py_GREENLETOBJECT_H + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is deprecated and undocumented. It does not change. */ +#define GREENLET_VERSION "1.0.0" + +#ifndef GREENLET_MODULE +#define implementation_ptr_t void* +#endif + +typedef struct _greenlet { + PyObject_HEAD + PyObject* weakreflist; + PyObject* dict; + implementation_ptr_t pimpl; +} PyGreenlet; + +#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type)) + + +/* C API functions */ + +/* Total number of symbols that are exported */ +#define PyGreenlet_API_pointers 12 + +#define PyGreenlet_Type_NUM 0 +#define PyExc_GreenletError_NUM 1 +#define PyExc_GreenletExit_NUM 2 + +#define PyGreenlet_New_NUM 3 +#define PyGreenlet_GetCurrent_NUM 4 +#define PyGreenlet_Throw_NUM 5 +#define PyGreenlet_Switch_NUM 6 +#define PyGreenlet_SetParent_NUM 7 + +#define PyGreenlet_MAIN_NUM 8 +#define PyGreenlet_STARTED_NUM 9 +#define PyGreenlet_ACTIVE_NUM 10 +#define PyGreenlet_GET_PARENT_NUM 11 + +#ifndef GREENLET_MODULE +/* This section is used by modules that uses the greenlet C API */ +static void** _PyGreenlet_API = NULL; + +# define PyGreenlet_Type \ + (*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM]) + +# define PyExc_GreenletError \ + ((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM]) + +# define PyExc_GreenletExit \ + ((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM]) + +/* + * PyGreenlet_New(PyObject *args) + * + * greenlet.greenlet(run, parent=None) + */ +# define PyGreenlet_New \ + (*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \ + _PyGreenlet_API[PyGreenlet_New_NUM]) + +/* + * PyGreenlet_GetCurrent(void) + * + * greenlet.getcurrent() + */ +# define PyGreenlet_GetCurrent \ + (*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM]) + +/* + * PyGreenlet_Throw( + * PyGreenlet *greenlet, + * PyObject *typ, + * PyObject *val, + * PyObject *tb) + * + * g.throw(...) + */ +# define PyGreenlet_Throw \ + (*(PyObject * (*)(PyGreenlet * self, \ + PyObject * typ, \ + PyObject * val, \ + PyObject * tb)) \ + _PyGreenlet_API[PyGreenlet_Throw_NUM]) + +/* + * PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args) + * + * g.switch(*args, **kwargs) + */ +# define PyGreenlet_Switch \ + (*(PyObject * \ + (*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \ + _PyGreenlet_API[PyGreenlet_Switch_NUM]) + +/* + * PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent) + * + * g.parent = new_parent + */ +# define PyGreenlet_SetParent \ + (*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \ + _PyGreenlet_API[PyGreenlet_SetParent_NUM]) + +/* + * PyGreenlet_GetParent(PyObject* greenlet) + * + * return greenlet.parent; + * + * This could return NULL even if there is no exception active. + * If it does not return NULL, you are responsible for decrementing the + * reference count. + */ +# define PyGreenlet_GetParent \ + (*(PyGreenlet* (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_GET_PARENT_NUM]) + +/* + * deprecated, undocumented alias. + */ +# define PyGreenlet_GET_PARENT PyGreenlet_GetParent + +# define PyGreenlet_MAIN \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_MAIN_NUM]) + +# define PyGreenlet_STARTED \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_STARTED_NUM]) + +# define PyGreenlet_ACTIVE \ + (*(int (*)(PyGreenlet*)) \ + _PyGreenlet_API[PyGreenlet_ACTIVE_NUM]) + + + + +/* Macro that imports greenlet and initializes C API */ +/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we + keep the older definition to be sure older code that might have a copy of + the header still works. */ +# define PyGreenlet_Import() \ + { \ + _PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \ + } + +#endif /* GREENLET_MODULE */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GREENLETOBJECT_H */