mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
routes working
This commit is contained in:
parent
72e9ced889
commit
748016bdab
69
invokeai/app/api/routers/board_images.py
Normal file
69
invokeai/app/api/routers/board_images.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from fastapi import Body, HTTPException, Path, Query
|
||||||
|
from fastapi.routing import APIRouter
|
||||||
|
from invokeai.app.services.board_record_storage import BoardRecord, BoardChanges
|
||||||
|
from invokeai.app.services.image_record_storage import OffsetPaginatedResults
|
||||||
|
from invokeai.app.services.models.board_record import BoardDTO
|
||||||
|
from invokeai.app.services.models.image_record import ImageDTO
|
||||||
|
|
||||||
|
from ..dependencies import ApiDependencies
|
||||||
|
|
||||||
|
board_images_router = APIRouter(prefix="/v1/board_images", tags=["boards"])
|
||||||
|
|
||||||
|
|
||||||
|
@board_images_router.post(
|
||||||
|
"/",
|
||||||
|
operation_id="create_board_image",
|
||||||
|
responses={
|
||||||
|
201: {"description": "The image was added to a board successfully"},
|
||||||
|
},
|
||||||
|
status_code=201,
|
||||||
|
)
|
||||||
|
async def create_board_image(
|
||||||
|
board_id: str = Body(description="The id of the board to add to"),
|
||||||
|
image_name: str = Body(description="The name of the image to add"),
|
||||||
|
):
|
||||||
|
"""Creates a board_image"""
|
||||||
|
try:
|
||||||
|
result = ApiDependencies.invoker.services.board_images.add_image_to_board(board_id=board_id, image_name=image_name)
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to add to board")
|
||||||
|
|
||||||
|
@board_images_router.delete(
|
||||||
|
"/",
|
||||||
|
operation_id="remove_board_image",
|
||||||
|
responses={
|
||||||
|
201: {"description": "The image was removed from the board successfully"},
|
||||||
|
},
|
||||||
|
status_code=201,
|
||||||
|
)
|
||||||
|
async def remove_board_image(
|
||||||
|
board_id: str = Body(description="The id of the board"),
|
||||||
|
image_name: str = Body(description="The name of the image to remove"),
|
||||||
|
):
|
||||||
|
"""Deletes a board_image"""
|
||||||
|
try:
|
||||||
|
result = ApiDependencies.invoker.services.board_images.remove_image_from_board(board_id=board_id, image_name=image_name)
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to update board")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@board_images_router.get(
|
||||||
|
"/{board_id}",
|
||||||
|
operation_id="list_board_images",
|
||||||
|
response_model=OffsetPaginatedResults[ImageDTO],
|
||||||
|
)
|
||||||
|
async def list_board_images(
|
||||||
|
board_id: str = Path(description="The id of the board"),
|
||||||
|
offset: int = Query(default=0, description="The page offset"),
|
||||||
|
limit: int = Query(default=10, description="The number of boards per page"),
|
||||||
|
) -> OffsetPaginatedResults[ImageDTO]:
|
||||||
|
"""Gets a list of images for a board"""
|
||||||
|
|
||||||
|
results = ApiDependencies.invoker.services.board_images.get_images_for_board(
|
||||||
|
board_id,
|
||||||
|
)
|
||||||
|
return results
|
||||||
|
|
@ -1,86 +1,79 @@
|
|||||||
# from fastapi import Body, HTTPException, Path, Query
|
from fastapi import Body, HTTPException, Path, Query
|
||||||
# from fastapi.routing import APIRouter
|
from fastapi.routing import APIRouter
|
||||||
# from invokeai.app.services.board_record_storage import BoardRecord, BoardChanges
|
from invokeai.app.services.board_record_storage import BoardRecord, BoardChanges
|
||||||
# from invokeai.app.services.image_record_storage import OffsetPaginatedResults
|
from invokeai.app.services.image_record_storage import OffsetPaginatedResults
|
||||||
|
from invokeai.app.services.models.board_record import BoardDTO
|
||||||
|
|
||||||
# from ..dependencies import ApiDependencies
|
from ..dependencies import ApiDependencies
|
||||||
|
|
||||||
# boards_router = APIRouter(prefix="/v1/boards", tags=["boards"])
|
boards_router = APIRouter(prefix="/v1/boards", tags=["boards"])
|
||||||
|
|
||||||
|
|
||||||
# @boards_router.post(
|
@boards_router.post(
|
||||||
# "/",
|
"/",
|
||||||
# operation_id="create_board",
|
operation_id="create_board",
|
||||||
# responses={
|
responses={
|
||||||
# 201: {"description": "The board was created successfully"},
|
201: {"description": "The board was created successfully"},
|
||||||
# },
|
},
|
||||||
# status_code=201,
|
status_code=201,
|
||||||
# )
|
)
|
||||||
# async def create_board(
|
async def create_board(
|
||||||
# board_name: str = Body(description="The name of the board to create"),
|
board_name: str = Body(description="The name of the board to create"),
|
||||||
# ):
|
):
|
||||||
# """Creates a board"""
|
"""Creates a board"""
|
||||||
# try:
|
try:
|
||||||
# result = ApiDependencies.invoker.services.boards.save(board_name=board_name)
|
result = ApiDependencies.invoker.services.boards.create(board_name=board_name)
|
||||||
# return result
|
return result
|
||||||
# except Exception as e:
|
except Exception as e:
|
||||||
# raise HTTPException(status_code=500, detail="Failed to create board")
|
raise HTTPException(status_code=500, detail="Failed to create board")
|
||||||
|
|
||||||
|
@boards_router.patch(
|
||||||
|
"/{board_id}",
|
||||||
|
operation_id="update_board",
|
||||||
|
responses={
|
||||||
|
201: {"description": "The board was updated successfully"},
|
||||||
|
},
|
||||||
|
status_code=201,
|
||||||
|
)
|
||||||
|
async def update_board(
|
||||||
|
board_id: str = Path(description="The id of board to update"),
|
||||||
|
changes: BoardChanges = Body(description="The changes to apply to the board"),
|
||||||
|
):
|
||||||
|
"""Creates a board"""
|
||||||
|
try:
|
||||||
|
result = ApiDependencies.invoker.services.boards.update(board_id=board_id, changes=changes)
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to update board")
|
||||||
|
|
||||||
|
|
||||||
# @boards_router.delete("/{board_id}", operation_id="delete_board")
|
@boards_router.delete("/{board_id}", operation_id="delete_board")
|
||||||
# async def delete_board(
|
async def delete_board(
|
||||||
# board_id: str = Path(description="The id of board to delete"),
|
board_id: str = Path(description="The id of board to delete"),
|
||||||
# ) -> None:
|
) -> None:
|
||||||
# """Deletes a board"""
|
"""Deletes a board"""
|
||||||
|
|
||||||
# try:
|
try:
|
||||||
# ApiDependencies.invoker.services.boards.delete(board_id=board_id)
|
ApiDependencies.invoker.services.boards.delete(board_id=board_id)
|
||||||
# except Exception as e:
|
except Exception as e:
|
||||||
# # TODO: Does this need any exception handling at all?
|
# TODO: Does this need any exception handling at all?
|
||||||
# pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# @boards_router.get(
|
@boards_router.get(
|
||||||
# "/",
|
"/",
|
||||||
# operation_id="list_boards",
|
operation_id="list_boards",
|
||||||
# response_model=OffsetPaginatedResults[BoardRecord],
|
response_model=OffsetPaginatedResults[BoardRecord],
|
||||||
# )
|
)
|
||||||
# async def list_boards(
|
async def list_boards(
|
||||||
# offset: int = Query(default=0, description="The page offset"),
|
offset: int = Query(default=0, description="The page offset"),
|
||||||
# limit: int = Query(default=10, description="The number of boards per page"),
|
limit: int = Query(default=10, description="The number of boards per page"),
|
||||||
# ) -> OffsetPaginatedResults[BoardRecord]:
|
) -> OffsetPaginatedResults[BoardDTO]:
|
||||||
# """Gets a list of boards"""
|
"""Gets a list of boards"""
|
||||||
|
|
||||||
# results = ApiDependencies.invoker.services.boards.get_many(
|
results = ApiDependencies.invoker.services.boards.get_many(
|
||||||
# offset,
|
offset,
|
||||||
# limit,
|
limit,
|
||||||
# )
|
)
|
||||||
|
return results
|
||||||
|
|
||||||
# boards = list(
|
|
||||||
# map(
|
|
||||||
# lambda r: board_record_to_dto(
|
|
||||||
# r,
|
|
||||||
# generate_cover_photo_url(r.id)
|
|
||||||
# ),
|
|
||||||
# results.boards,
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# return boards
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# def board_record_to_dto(
|
|
||||||
# board_record: BoardRecord, cover_image_url: str
|
|
||||||
# ) -> BoardDTO:
|
|
||||||
# """Converts an image record to an image DTO."""
|
|
||||||
# return BoardDTO(
|
|
||||||
# **board_record.dict(),
|
|
||||||
# cover_image_url=cover_image_url,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# def generate_cover_photo_url(board_id: str) -> str | None:
|
|
||||||
# cover_photo = ApiDependencies.invoker.services.images._services.records.get_board_cover_photo(board_id)
|
|
||||||
# if cover_photo is not None:
|
|
||||||
# url = ApiDependencies.invoker.services.images._services.urls.get_image_url(cover_photo.image_origin, cover_photo.image_name)
|
|
||||||
# return url
|
|
||||||
|
@ -24,7 +24,7 @@ logger = InvokeAILogger.getLogger(config=app_config)
|
|||||||
import invokeai.frontend.web as web_dir
|
import invokeai.frontend.web as web_dir
|
||||||
|
|
||||||
from .api.dependencies import ApiDependencies
|
from .api.dependencies import ApiDependencies
|
||||||
from .api.routers import sessions, models, images, boards
|
from .api.routers import sessions, models, images, boards, board_images
|
||||||
from .api.sockets import SocketIO
|
from .api.sockets import SocketIO
|
||||||
from .invocations.baseinvocation import BaseInvocation
|
from .invocations.baseinvocation import BaseInvocation
|
||||||
|
|
||||||
@ -78,7 +78,9 @@ app.include_router(models.models_router, prefix="/api")
|
|||||||
|
|
||||||
app.include_router(images.images_router, prefix="/api")
|
app.include_router(images.images_router, prefix="/api")
|
||||||
|
|
||||||
# app.include_router(boards.boards_router, prefix="/api")
|
app.include_router(boards.boards_router, prefix="/api")
|
||||||
|
|
||||||
|
app.include_router(board_images.board_images_router, prefix="/api")
|
||||||
|
|
||||||
# Build a custom OpenAPI to include all outputs
|
# Build a custom OpenAPI to include all outputs
|
||||||
# TODO: can outputs be included on metadata of invocation schemas somehow?
|
# TODO: can outputs be included on metadata of invocation schemas somehow?
|
||||||
|
@ -2,7 +2,6 @@ from abc import ABC, abstractmethod
|
|||||||
from logging import Logger
|
from logging import Logger
|
||||||
from invokeai.app.services.board_image_record_storage import BoardImageRecordStorageBase
|
from invokeai.app.services.board_image_record_storage import BoardImageRecordStorageBase
|
||||||
from invokeai.app.services.board_record_storage import (
|
from invokeai.app.services.board_record_storage import (
|
||||||
BoardDTO,
|
|
||||||
BoardRecord,
|
BoardRecord,
|
||||||
BoardRecordStorageBase,
|
BoardRecordStorageBase,
|
||||||
)
|
)
|
||||||
@ -11,6 +10,7 @@ from invokeai.app.services.image_record_storage import (
|
|||||||
ImageRecordStorageBase,
|
ImageRecordStorageBase,
|
||||||
OffsetPaginatedResults,
|
OffsetPaginatedResults,
|
||||||
)
|
)
|
||||||
|
from invokeai.app.services.models.board_record import BoardDTO
|
||||||
from invokeai.app.services.models.image_record import ImageDTO, image_record_to_dto
|
from invokeai.app.services.models.image_record import ImageDTO, image_record_to_dto
|
||||||
from invokeai.app.services.urls import UrlServiceBase
|
from invokeai.app.services.urls import UrlServiceBase
|
||||||
|
|
||||||
|
@ -6,41 +6,11 @@ import threading
|
|||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
import uuid
|
import uuid
|
||||||
from invokeai.app.services.image_record_storage import OffsetPaginatedResults
|
from invokeai.app.services.image_record_storage import OffsetPaginatedResults
|
||||||
|
from invokeai.app.services.models.board_record import BoardRecord, deserialize_board_record
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, Extra
|
from pydantic import BaseModel, Field, Extra
|
||||||
|
|
||||||
|
|
||||||
class BoardRecord(BaseModel):
|
|
||||||
"""Deserialized board record."""
|
|
||||||
|
|
||||||
board_id: str = Field(description="The unique ID of the board.")
|
|
||||||
"""The unique ID of the board."""
|
|
||||||
board_name: str = Field(description="The name of the board.")
|
|
||||||
"""The name of the board."""
|
|
||||||
created_at: Union[datetime, str] = Field(
|
|
||||||
description="The created timestamp of the board."
|
|
||||||
)
|
|
||||||
"""The created timestamp of the image."""
|
|
||||||
updated_at: Union[datetime, str] = Field(
|
|
||||||
description="The updated timestamp of the board."
|
|
||||||
)
|
|
||||||
"""The updated timestamp of the image."""
|
|
||||||
cover_image_name: Optional[str] = Field(
|
|
||||||
description="The name of the cover image of the board."
|
|
||||||
)
|
|
||||||
"""The name of the cover image of the board."""
|
|
||||||
|
|
||||||
|
|
||||||
class BoardDTO(BoardRecord):
|
|
||||||
"""Deserialized board record with cover image URL and image count."""
|
|
||||||
|
|
||||||
cover_image_url: Optional[str] = Field(
|
|
||||||
description="The URL of the thumbnail of the board's cover image."
|
|
||||||
)
|
|
||||||
"""The URL of the thumbnail of the most recent image in the board."""
|
|
||||||
image_count: int = Field(description="The number of images in the board.")
|
|
||||||
"""The number of images in the board."""
|
|
||||||
|
|
||||||
|
|
||||||
class BoardChanges(BaseModel, extra=Extra.forbid):
|
class BoardChanges(BaseModel, extra=Extra.forbid):
|
||||||
board_name: Optional[str] = Field(description="The board's new name.")
|
board_name: Optional[str] = Field(description="The board's new name.")
|
||||||
@ -221,6 +191,7 @@ class SqliteBoardRecordStorage(BoardRecordStorageBase):
|
|||||||
return BoardRecord(**result)
|
return BoardRecord(**result)
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
self._conn.rollback()
|
self._conn.rollback()
|
||||||
|
print(e)
|
||||||
raise BoardRecordSaveException from e
|
raise BoardRecordSaveException from e
|
||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
@ -307,7 +278,7 @@ class SqliteBoardRecordStorage(BoardRecordStorageBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
result = cast(list[sqlite3.Row], self._cursor.fetchall())
|
result = cast(list[sqlite3.Row], self._cursor.fetchall())
|
||||||
boards = [BoardRecord(**dict(row)) for row in result]
|
boards = list(map(lambda r: deserialize_board_record(dict(r)), result))
|
||||||
|
|
||||||
# Get the total number of boards
|
# Get the total number of boards
|
||||||
self._cursor.execute(
|
self._cursor.execute(
|
||||||
|
@ -5,8 +5,6 @@ from invokeai.app.services.board_image_record_storage import BoardImageRecordSto
|
|||||||
from invokeai.app.services.board_images import board_record_to_dto
|
from invokeai.app.services.board_images import board_record_to_dto
|
||||||
|
|
||||||
from invokeai.app.services.board_record_storage import (
|
from invokeai.app.services.board_record_storage import (
|
||||||
BoardDTO,
|
|
||||||
BoardRecord,
|
|
||||||
BoardChanges,
|
BoardChanges,
|
||||||
BoardRecordStorageBase,
|
BoardRecordStorageBase,
|
||||||
)
|
)
|
||||||
@ -14,7 +12,7 @@ from invokeai.app.services.image_record_storage import (
|
|||||||
ImageRecordStorageBase,
|
ImageRecordStorageBase,
|
||||||
OffsetPaginatedResults,
|
OffsetPaginatedResults,
|
||||||
)
|
)
|
||||||
from invokeai.app.services.models.image_record import ImageDTO
|
from invokeai.app.services.models.board_record import BoardDTO
|
||||||
from invokeai.app.services.urls import UrlServiceBase
|
from invokeai.app.services.urls import UrlServiceBase
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,17 +261,6 @@ class SqliteImageRecordStorage(ImageRecordStorageBase):
|
|||||||
(changes.is_intermediate, image_name),
|
(changes.is_intermediate, image_name),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Change the image's `is_intermediate`` flag
|
|
||||||
if changes.is_intermediate is not None:
|
|
||||||
self._cursor.execute(
|
|
||||||
f"""--sql
|
|
||||||
UPDATE images
|
|
||||||
SET board_id = ?
|
|
||||||
WHERE image_name = ?;
|
|
||||||
""",
|
|
||||||
(changes.is_intermediate, image_name),
|
|
||||||
)
|
|
||||||
|
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
self._conn.rollback()
|
self._conn.rollback()
|
||||||
|
57
invokeai/app/services/models/board_record.py
Normal file
57
invokeai/app/services/models/board_record.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
from typing import Optional, Union
|
||||||
|
from datetime import datetime
|
||||||
|
from pydantic import BaseModel, Extra, Field, StrictBool, StrictStr
|
||||||
|
from invokeai.app.util.misc import get_iso_timestamp
|
||||||
|
|
||||||
|
class BoardRecord(BaseModel):
|
||||||
|
"""Deserialized board record."""
|
||||||
|
|
||||||
|
board_id: str = Field(description="The unique ID of the board.")
|
||||||
|
"""The unique ID of the board."""
|
||||||
|
board_name: str = Field(description="The name of the board.")
|
||||||
|
"""The name of the board."""
|
||||||
|
created_at: Union[datetime, str] = Field(
|
||||||
|
description="The created timestamp of the board."
|
||||||
|
)
|
||||||
|
"""The created timestamp of the image."""
|
||||||
|
updated_at: Union[datetime, str] = Field(
|
||||||
|
description="The updated timestamp of the board."
|
||||||
|
)
|
||||||
|
"""The updated timestamp of the image."""
|
||||||
|
cover_image_name: Optional[str] = Field(
|
||||||
|
description="The name of the cover image of the board."
|
||||||
|
)
|
||||||
|
"""The name of the cover image of the board."""
|
||||||
|
|
||||||
|
|
||||||
|
class BoardDTO(BoardRecord):
|
||||||
|
"""Deserialized board record with cover image URL and image count."""
|
||||||
|
|
||||||
|
cover_image_url: Optional[str] = Field(
|
||||||
|
description="The URL of the thumbnail of the board's cover image."
|
||||||
|
)
|
||||||
|
"""The URL of the thumbnail of the most recent image in the board."""
|
||||||
|
image_count: int = Field(description="The number of images in the board.")
|
||||||
|
"""The number of images in the board."""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def deserialize_board_record(board_dict: dict) -> BoardRecord:
|
||||||
|
"""Deserializes a board record."""
|
||||||
|
|
||||||
|
# Retrieve all the values, setting "reasonable" defaults if they are not present.
|
||||||
|
|
||||||
|
board_id = board_dict.get("board_id", "unknown")
|
||||||
|
board_name = board_dict.get("board_name", "unknown")
|
||||||
|
created_at = board_dict.get("created_at", get_iso_timestamp())
|
||||||
|
updated_at = board_dict.get("updated_at", get_iso_timestamp())
|
||||||
|
deleted_at = board_dict.get("deleted_at", get_iso_timestamp())
|
||||||
|
|
||||||
|
return BoardRecord(
|
||||||
|
board_id=board_id,
|
||||||
|
board_name=board_name,
|
||||||
|
created_at=created_at,
|
||||||
|
updated_at=updated_at,
|
||||||
|
deleted_at=deleted_at,
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user