Metadata-Version: 2.4
Name: nautica
Version: 3.1.0
Summary: A service management framework
Author-email: Xellu <xellu@catboys.cc>
License: MIT
Project-URL: Homepage, https://github.com/xellu/nautica-api
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: starlette
Requires-Dist: uvicorn
Requires-Dist: python-multipart
Requires-Dist: colorama
Requires-Dist: tomlkit
Requires-Dist: click
Requires-Dist: psutil
Requires-Dist: textual
Requires-Dist: pathspec
Requires-Dist: requests
Requires-Dist: packaging
Dynamic: license-file

# Nautica V3

![PyPI Version](https://img.shields.io/pypi/v/nautica)
![Python](https://img.shields.io/badge/python-3.11+-blue)
![License](https://img.shields.io/github/license/xellu/nautica-api)
![PyPI Downloads](https://img.shields.io/pypi/dm/nautica)

Nautica V3 _(or N3)_ is a backend platform for Python. It gives you a managed runtime environment with a service registry, lifecycle system, CLI, and built-in 
tools, saving you time from putting your app together and giving you more time to build it.

<img width="1589" height="690" alt="hjkl rsdfgkhjlfgjkl" src="https://github.com/user-attachments/assets/e32e112b-5e62-4e0e-aeae-e6fdd0a36d90" />

## What's Included
- **Service Registry** with dependency resolver
- **Lifecycle hooks** for install, start and shutdown
- TOML **Config system** with key management
- **Logger** with file output and memory
- **Shell** for interacting with services
- **TUI** for live logs, thread and worker inspection _(optional)_
- **Plugin system** for extending projects without modifying core code
- Many Built-in **Services**, including **HTTP API**

***

I made N3 because I was solving the same problems in my projects, those being: configs, logging, figuring out startup orders, not to mention the validation boilerplate on every route. Because of this I made Nautica V2, which solved many of these issues, and V3 to improve on the idea.

## Get Started

Firstly, install Nautica:
```bash
pip install nautica
```

To create a project, use the CLI ([docs](https://github.com/xellu/nautica-api/wiki/CLI-Reference)):
```bash
nautica create my-project
cd my-project
nautica run
```

To setup an existing project:
```bash
cd my-project
nautica install
nautica run
```

***

## How HTTP API Compares

### Benchmark Performance

| Library | Requests/Second | Avg Latency | Overall |
| --- | --- | --- | --- |
| Nautica3 | `2271` | `4.4ms` | - |
| FastAPI | `2259` | `4.4ms` | 0.5% slower |
| Flask | `75` | `132.6ms` | 96% slower |

*Ran with 10 workers, for 10 seconds. Nautica3 matches FastAPI despite running additional middleware, requirement parsing, and logging on every request.*

### Code Complexity

Similarly to SvelteKit, Nautica defines the route names for you. This helps to reduce boilerplate (see Flask and FastAPI examples), improve readability, and helps with naming conventions

#### Nautica3
```py
# file: src/http/api/v1/auth.py
from napi.http import HTTP, Context, Reply
from somewhere import username, password

@HTTP.POST()
@HTTP.Require(body = {"username": str, "password": str})
def login(ctx: Context):
    if ctx.body["username"] == username and ctx.body["password"] == password:
        return Reply(ok=True)
    return Reply(ok=False, error="Invalid credentials"), 401
```

#### Flask
```py
# file: main.py
from flask import Flask, request
from flask.blueprints import Blueprint
import json
from somewhere import username, password

app = Flask(__name__)
v1auth = Blueprint("v1auth", __name__, url_prefix="/api/v1/auth")

@v1auth.post("/login")
def login():
    data = request.get_json(silent=True) or {}
    if data.get("username") == username and data.get("password") == password:
        return json.dumps({"ok": True})
    return json.dumps({"ok": False, "error": "Invalid credentials"}), 401

app.register_blueprint(v1auth)
app.run(port=8101)
```

#### FastAPI
```py
# file: main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uvicorn
from somewhere import username, password

app = FastAPI()

class LoginRequest(BaseModel):
    username: str
    password: str

@app.post("/api/v1/auth/login")
def login(body: LoginRequest):
    if body.username == username and body.password == password:
        return {"ok": True}
    raise HTTPException(status_code=401, detail="Invalid credentials")

uvicorn.run(app, port=8101)
```
