mirror of
https://github.com/tcsenpai/pensieve.git
synced 2025-06-09 12:37:12 +00:00
feat: update schemas
This commit is contained in:
parent
193b93bccc
commit
929b81ff41
26
memos/crud.py
Normal file
26
memos/crud.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from .schemas import Library, NewLibraryParam, Folder
|
||||||
|
from .models import LibraryModel, FolderModel
|
||||||
|
|
||||||
|
|
||||||
|
def get_library_by_id(library_id: int, db: Session) -> Library | None:
|
||||||
|
return db.query(Library).filter(Library.id == library_id).first()
|
||||||
|
|
||||||
|
|
||||||
|
def create_library(library: NewLibraryParam, db: Session) -> Library:
|
||||||
|
db_library = LibraryModel(name=library.name)
|
||||||
|
db.add(db_library)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_library)
|
||||||
|
|
||||||
|
for folder_path in library.folders:
|
||||||
|
db_folder = FolderModel(path=str(folder_path), library_id=db_library.id)
|
||||||
|
db.add(db_folder)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
return Library(
|
||||||
|
id=db_library.id,
|
||||||
|
name=db_library.name,
|
||||||
|
folders=[Folder(id=db_folder.id, name=db_folder.path) for db_folder in db_library.folders],
|
||||||
|
plugins=[]
|
||||||
|
)
|
@ -5,6 +5,7 @@ from sqlalchemy import (
|
|||||||
Text,
|
Text,
|
||||||
DateTime,
|
DateTime,
|
||||||
Enum,
|
Enum,
|
||||||
|
ForeignKey,
|
||||||
func
|
func
|
||||||
)
|
)
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -30,7 +31,7 @@ class LibraryModel(Base):
|
|||||||
class FolderModel(Base):
|
class FolderModel(Base):
|
||||||
__tablename__ = "folders"
|
__tablename__ = "folders"
|
||||||
path: Mapped[str] = mapped_column(String, nullable=False)
|
path: Mapped[str] = mapped_column(String, nullable=False)
|
||||||
library_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
library_id: Mapped[int] = mapped_column(Integer, ForeignKey('libraries.id'), nullable=False)
|
||||||
library: Mapped["LibraryModel"] = relationship("LibraryModel", back_populates="folders")
|
library: Mapped["LibraryModel"] = relationship("LibraryModel", back_populates="folders")
|
||||||
entities: Mapped[List["EntityModel"]] = relationship("EntityModel", back_populates="folder")
|
entities: Mapped[List["EntityModel"]] = relationship("EntityModel", back_populates="folder")
|
||||||
|
|
||||||
@ -44,10 +45,11 @@ class EntityModel(Base):
|
|||||||
file_last_modified_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
|
file_last_modified_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
|
||||||
file_type: Mapped[str] = mapped_column(String, nullable=False)
|
file_type: Mapped[str] = mapped_column(String, nullable=False)
|
||||||
last_scan_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
last_scan_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||||
folder_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
library_id: Mapped[int] = mapped_column(Integer, ForeignKey('libraries.id'), nullable=False)
|
||||||
|
folder_id: Mapped[int] = mapped_column(Integer, ForeignKey('folders.id'), nullable=False)
|
||||||
folder: Mapped["FolderModel"] = relationship("FolderModel", back_populates="entities")
|
folder: Mapped["FolderModel"] = relationship("FolderModel", back_populates="entities")
|
||||||
metadata_entries: Mapped[List["EntityMetadataModel"]] = relationship("EntityMetadataModel", back_populates="entity")
|
metadata_entries: Mapped[List["EntityMetadataModel"]] = relationship("EntityMetadataModel")
|
||||||
tags: Mapped[List["TagModel"]] = relationship("EntityTagModel", back_populates="entity")
|
tags: Mapped[List["TagModel"]] = relationship("EntityTagModel")
|
||||||
|
|
||||||
|
|
||||||
class TagModel(Base):
|
class TagModel(Base):
|
||||||
@ -60,19 +62,19 @@ class TagModel(Base):
|
|||||||
|
|
||||||
class EntityTagModel(Base):
|
class EntityTagModel(Base):
|
||||||
__tablename__ = "entity_tags"
|
__tablename__ = "entity_tags"
|
||||||
entity_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
entity_id: Mapped[int] = mapped_column(Integer, ForeignKey('entities.id'), nullable=False)
|
||||||
tag_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
tag_id: Mapped[int] = mapped_column(Integer, ForeignKey('tags.id'), nullable=False)
|
||||||
source: Mapped[MetadataSource] = mapped_column(Enum(MetadataSource), nullable=False)
|
source: Mapped[MetadataSource] = mapped_column(Enum(MetadataSource), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class EntityMetadataModel(Base):
|
class EntityMetadataModel(Base):
|
||||||
__tablename__ = "metadata_entries"
|
__tablename__ = "metadata_entries"
|
||||||
entity_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
entity_id: Mapped[int] = mapped_column(Integer, ForeignKey('entities.id'), nullable=False)
|
||||||
key: Mapped[str] = mapped_column(String, nullable=False)
|
key: Mapped[str] = mapped_column(String, nullable=False)
|
||||||
value: Mapped[str] = mapped_column(Text, nullable=False)
|
value: Mapped[str] = mapped_column(Text, nullable=False)
|
||||||
source_type: Mapped[MetadataSource] = mapped_column(Enum(MetadataSource), nullable=False)
|
source_type: Mapped[MetadataSource] = mapped_column(Enum(MetadataSource), nullable=False)
|
||||||
source: Mapped[str | None] = mapped_column(String, nullable=True)
|
source: Mapped[str | None] = mapped_column(String, nullable=True)
|
||||||
datetype: Mapped[MetadataType] = mapped_column(Enum(MetadataType), nullable=False)
|
date_type: Mapped[MetadataType] = mapped_column(Enum(MetadataType), nullable=False)
|
||||||
entity = relationship("EntityModel", back_populates="metadata_entries")
|
entity = relationship("EntityModel", back_populates="metadata_entries")
|
||||||
|
|
||||||
|
|
||||||
@ -86,12 +88,12 @@ class PluginModel(Base):
|
|||||||
|
|
||||||
class LibraryPluginModel(Base):
|
class LibraryPluginModel(Base):
|
||||||
__tablename__ = "library_plugins"
|
__tablename__ = "library_plugins"
|
||||||
library_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
library_id: Mapped[int] = mapped_column(Integer, ForeignKey('libraries.id'), nullable=False)
|
||||||
plugin_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
plugin_id: Mapped[int] = mapped_column(Integer, ForeignKey('plugins.id'), nullable=False)
|
||||||
library: Mapped["LibraryModel"] = relationship("LibraryModel", back_populates="plugins")
|
library: Mapped["LibraryModel"] = relationship("LibraryModel", back_populates="plugins")
|
||||||
plugin: Mapped["PluginModel"] = relationship("PluginModel", back_populates="libraries")
|
plugin: Mapped["PluginModel"] = relationship("PluginModel", back_populates="libraries")
|
||||||
|
|
||||||
|
|
||||||
# Create the database engine with the path from config
|
# Create the database engine with the path from config
|
||||||
engine = create_engine(f"sqlite:///{get_database_path()}", echo=True)
|
engine = create_engine(f"sqlite:///:memory:", echo=True)
|
||||||
Base.metadata.create_all(engine)
|
Base.metadata.create_all(engine)
|
||||||
|
127
memos/schemas.py
Normal file
127
memos/schemas.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
from pydantic import BaseModel, ConfigDict, DirectoryPath, HttpUrl, field_validator
|
||||||
|
from typing import List
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataSource(Enum):
|
||||||
|
USER_GENERATED = "user_generated"
|
||||||
|
SYSTEM_GENERATED = "system_generated"
|
||||||
|
PLUGIN_GENERATED = "plugin_generated"
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataType(Enum):
|
||||||
|
EXTRACONTENT = "extra_content"
|
||||||
|
ATTRIBUTE = "attribute"
|
||||||
|
|
||||||
|
|
||||||
|
class NewLibraryParam(BaseModel):
|
||||||
|
name: str
|
||||||
|
folders: List[DirectoryPath] = []
|
||||||
|
|
||||||
|
|
||||||
|
class NewFolderParam(BaseModel):
|
||||||
|
path: DirectoryPath
|
||||||
|
|
||||||
|
|
||||||
|
class NewEntityParam(BaseModel):
|
||||||
|
filename: str
|
||||||
|
path: str
|
||||||
|
size: int
|
||||||
|
created_at: datetime
|
||||||
|
file_created_at: datetime
|
||||||
|
file_last_modified_at: datetime
|
||||||
|
file_type: str
|
||||||
|
folder_id: int
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateTagParam(BaseModel):
|
||||||
|
description: str | None
|
||||||
|
color: str | None
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateEntityTagsParam(BaseModel):
|
||||||
|
tags: List[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
class EntityMetadataParam(BaseModel):
|
||||||
|
key: str
|
||||||
|
value: str
|
||||||
|
source: MetadataSource
|
||||||
|
data_type: MetadataType
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateEntityMetadataParam(BaseModel):
|
||||||
|
metadata_entries: List[EntityMetadataParam]
|
||||||
|
|
||||||
|
|
||||||
|
class NewPluginParam(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: str | None
|
||||||
|
webhook_url: HttpUrl
|
||||||
|
|
||||||
|
|
||||||
|
class NewLibraryPluginParam(BaseModel):
|
||||||
|
plugin_id: int
|
||||||
|
|
||||||
|
|
||||||
|
class Folder(BaseModel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(BaseModel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
description: str | None
|
||||||
|
webhook_url: str
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Library(BaseModel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
folders: List[Folder] = []
|
||||||
|
plugins: List[Plugin] = []
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Entity(BaseModel):
|
||||||
|
id: int
|
||||||
|
path: str
|
||||||
|
filename: str
|
||||||
|
size: int
|
||||||
|
file_created_at: datetime
|
||||||
|
file_last_modified_at: datetime
|
||||||
|
file_type: str
|
||||||
|
last_scan_at: datetime | None
|
||||||
|
folder_id: int
|
||||||
|
library_id: int
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Tag(BaseModel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
description: str | None
|
||||||
|
color: str | None
|
||||||
|
created_at: datetime
|
||||||
|
source: str
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
|
||||||
|
class EntityMetadata(BaseModel):
|
||||||
|
id: int
|
||||||
|
entity_id: int
|
||||||
|
key: str
|
||||||
|
value: str
|
||||||
|
source: str
|
||||||
|
date_type: MetadataType
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
@ -1,4 +1,90 @@
|
|||||||
import uvicorn
|
import uvicorn
|
||||||
|
from fastapi import FastAPI, HTTPException, Depends, status
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from .config import get_database_path
|
||||||
|
from .crud import get_library_by_id, create_library
|
||||||
|
from .schemas import (
|
||||||
|
Library,
|
||||||
|
Folder,
|
||||||
|
Entity,
|
||||||
|
Plugin,
|
||||||
|
NewLibraryParam,
|
||||||
|
NewFolderParam,
|
||||||
|
NewEntityParam,
|
||||||
|
NewPluginParam,
|
||||||
|
NewLibraryPluginParam,
|
||||||
|
)
|
||||||
|
|
||||||
|
engine = create_engine(f"sqlite:///{get_database_path()}")
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/libraries", response_model=Library)
|
||||||
|
def new_library(library_param: NewLibraryParam, db: Session = Depends(get_db)):
|
||||||
|
library = create_library(library_param, db)
|
||||||
|
return library
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/libraries/{library_id}/folders", response_model=Folder)
|
||||||
|
def new_folder(
|
||||||
|
library_id: int,
|
||||||
|
folder: NewFolderParam, db: Session = Depends(get_db),
|
||||||
|
):
|
||||||
|
library = get_library_by_id(library_id, db)
|
||||||
|
if library is None:
|
||||||
|
raise HTTPException(status_code=404, detail="Library not found")
|
||||||
|
|
||||||
|
db_folder = Folder(path=folder.path, library_id=library.id)
|
||||||
|
db.add(db_folder)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_folder)
|
||||||
|
return db_folder
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/libraries/{library_id}/entities", response_model=Entity)
|
||||||
|
def new_entity(
|
||||||
|
entity: NewEntityParam, library_id: int, db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
|
||||||
|
db_entity = Entity(**entity.model_dump(), library_id=library_id)
|
||||||
|
db.add(db_entity)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_entity)
|
||||||
|
return db_entity
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/plugins", response_model=Plugin)
|
||||||
|
def new_plugin(plugin: NewPluginParam, db: Session = Depends(get_db)):
|
||||||
|
db_plugin = Plugin(**plugin.model_dump())
|
||||||
|
db.add(db_plugin)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_plugin)
|
||||||
|
return db_plugin
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/libraries/{library_id}/plugins", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
def add_library_plugin(
|
||||||
|
library_id: int, plugin: NewLibraryPluginParam, db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
db_library_plugin = LibrayPlugin(library_id=library_id, plugin_id=plugin.plugin_id)
|
||||||
|
db.add(db_library_plugin)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_library_plugin)
|
||||||
|
|
||||||
|
|
||||||
def run_server():
|
def run_server():
|
||||||
uvicorn.run("memos.main:app", host="0.0.0.0", port=8080, reload=True)
|
uvicorn.run("memos.server:app", host="0.0.0.0", port=8080, reload=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user