diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 260a910bb..627c4bbb1 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -13,6 +13,7 @@ RUN echo "export PROMPT_COMMAND='history -a'" >> /home/vscode/.bashrc \ && chown vscode:vscode -R /home/vscode/ RUN npm install -g @go-task/cli +RUN npm install -g json-schema-to-typescript # Install additional OS packages RUN apt-get update \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 258d63fba..d00bd744d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,7 +23,6 @@ "settings": { "python.defaultInterpreterPath": "/usr/local/bin/python", "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", - "python.formatting.blackPath": "/usr/local/py-utils/bin/black", "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", "mypy.runUsingActiveInterpreter": true }, @@ -34,6 +33,7 @@ "ms-python.pylint", "ms-python.python", "ms-python.vscode-pylance", + "streetsidesoftware.code-spell-checker-cspell-bundled-dictionaries", "Vue.volar" ] } @@ -41,6 +41,7 @@ // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [ 3000, + 8000, // used by mkdocs 9000, 9091, // used by docker production 24678 // used by nuxt when hot-reloading using polling diff --git a/.gitignore b/.gitignore index b24f03a93..809f45abd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ dev/data/backups/* dev/data/debug/* dev/data/img/* dev/data/migration/* +dev/data/templates/* dev/data/users/* dev/data/groups/* diff --git a/frontend/lib/api/types/admin.ts b/frontend/lib/api/types/admin.ts index a596fc210..7d23672eb 100644 --- a/frontend/lib/api/types/admin.ts +++ b/frontend/lib/api/types/admin.ts @@ -110,80 +110,6 @@ export interface CreateBackup { options: BackupOptions; templates?: string[] | null; } -export interface CustomPageBase { - name: string; - slug: string | null; - position: number; - categories?: RecipeCategoryResponse[]; -} -export interface RecipeCategoryResponse { - name: string; - id: string; - groupId?: string | null; - slug: string; - recipes?: RecipeSummary[]; -} -export interface RecipeSummary { - id?: string | null; - userId?: string; - householdId?: string; - groupId?: string; - name?: string | null; - slug?: string; - image?: unknown; - recipeServings?: number; - recipeYieldQuantity?: number; - recipeYield?: string | null; - totalTime?: string | null; - prepTime?: string | null; - cookTime?: string | null; - performTime?: string | null; - description?: string | null; - recipeCategory?: RecipeCategory[] | null; - tags?: RecipeTag[] | null; - tools?: RecipeTool[]; - rating?: number | null; - orgURL?: string | null; - dateAdded?: string | null; - dateUpdated?: string | null; - createdAt?: string | null; - updatedAt?: string | null; - lastMade?: string | null; -} -export interface RecipeCategory { - id?: string | null; - groupId?: string | null; - name: string; - slug: string; - [k: string]: unknown; -} -export interface RecipeTag { - id?: string | null; - groupId?: string | null; - name: string; - slug: string; - [k: string]: unknown; -} -export interface RecipeTool { - id: string; - groupId?: string | null; - name: string; - slug: string; - householdsWithTool?: string[]; - [k: string]: unknown; -} -export interface CustomPageImport { - name: string; - status: boolean; - exception?: string | null; -} -export interface CustomPageOut { - name: string; - slug: string | null; - position: number; - categories?: RecipeCategoryResponse[]; - id: number; -} export interface DebugResponse { success: boolean; response?: string | null; @@ -248,11 +174,6 @@ export interface Migrations { type: string; files?: MigrationFile[]; } -export interface NotificationImport { - name: string; - status: boolean; - exception?: string | null; -} export interface RecipeImport { name: string; status: boolean; diff --git a/frontend/lib/api/types/cookbook.ts b/frontend/lib/api/types/cookbook.ts index 36f1c086f..e93386e0f 100644 --- a/frontend/lib/api/types/cookbook.ts +++ b/frontend/lib/api/types/cookbook.ts @@ -44,7 +44,6 @@ export interface QueryFilterJSONPart { attributeName?: string | null; relationalOperator?: RelationalKeyword | RelationalOperator | null; value?: string | string[] | null; - [k: string]: unknown; } export interface SaveCookBook { name: string; diff --git a/frontend/lib/api/types/household.ts b/frontend/lib/api/types/household.ts index 9ffc96d45..05a0abf42 100644 --- a/frontend/lib/api/types/household.ts +++ b/frontend/lib/api/types/household.ts @@ -334,7 +334,6 @@ export interface IngredientUnit { } export interface IngredientUnitAlias { name: string; - [k: string]: unknown; } export interface CreateIngredientUnit { id?: string | null; @@ -349,11 +348,9 @@ export interface CreateIngredientUnit { pluralAbbreviation?: string | null; useAbbreviation?: boolean; aliases?: CreateIngredientUnitAlias[]; - [k: string]: unknown; } export interface CreateIngredientUnitAlias { name: string; - [k: string]: unknown; } export interface IngredientFood { id: string; @@ -372,7 +369,6 @@ export interface IngredientFood { } export interface IngredientFoodAlias { name: string; - [k: string]: unknown; } export interface MultiPurposeLabelSummary { name: string; @@ -391,11 +387,9 @@ export interface CreateIngredientFood { labelId?: string | null; aliases?: CreateIngredientFoodAlias[]; householdsWithIngredientFood?: string[]; - [k: string]: unknown; } export interface CreateIngredientFoodAlias { name: string; - [k: string]: unknown; } export interface Recipe { id?: string | null; @@ -433,21 +427,18 @@ export interface Recipe { [k: string]: unknown; } | null; comments?: RecipeCommentOut[] | null; - [k: string]: unknown; } export interface RecipeCategory { id?: string | null; groupId?: string | null; name: string; slug: string; - [k: string]: unknown; } export interface RecipeTag { id?: string | null; groupId?: string | null; name: string; slug: string; - [k: string]: unknown; } export interface RecipeTool { id: string; @@ -455,7 +446,6 @@ export interface RecipeTool { name: string; slug: string; householdsWithTool?: string[]; - [k: string]: unknown; } export interface RecipeStep { id?: string | null; @@ -463,11 +453,9 @@ export interface RecipeStep { summary?: string | null; text: string; ingredientReferences?: IngredientReferences[]; - [k: string]: unknown; } export interface IngredientReferences { referenceId?: string | null; - [k: string]: unknown; } export interface Nutrition { calories?: string | null; @@ -481,7 +469,6 @@ export interface Nutrition { sugarContent?: string | null; transFatContent?: string | null; unsaturatedFatContent?: string | null; - [k: string]: unknown; } export interface RecipeSettings { public?: boolean; @@ -490,18 +477,15 @@ export interface RecipeSettings { landscapeView?: boolean; disableComments?: boolean; locked?: boolean; - [k: string]: unknown; } export interface RecipeAsset { name: string; icon: string; fileName?: string | null; - [k: string]: unknown; } export interface RecipeNote { title: string; text: string; - [k: string]: unknown; } export interface RecipeCommentOut { recipeId: string; @@ -511,14 +495,12 @@ export interface RecipeCommentOut { updatedAt: string; userId: string; user: UserBase; - [k: string]: unknown; } export interface UserBase { id: string; username?: string | null; admin: boolean; fullName?: string | null; - [k: string]: unknown; } export interface ShoppingListAddRecipeParamsBulk { recipeIncrementQuantity?: number; diff --git a/mealie/schema/_mealie/__init__.py b/mealie/schema/_mealie/__init__.py index 628e17908..7441e747a 100644 --- a/mealie/schema/_mealie/__init__.py +++ b/mealie/schema/_mealie/__init__.py @@ -3,11 +3,11 @@ from .datetime_parse import DateError, DateTimeError, DurationError, TimeError from .mealie_model import HasUUID, MealieModel, SearchType __all__ = [ + "HasUUID", + "MealieModel", + "SearchType", "DateError", "DateTimeError", "DurationError", "TimeError", - "HasUUID", - "MealieModel", - "SearchType", ] diff --git a/mealie/schema/admin/__init__.py b/mealie/schema/admin/__init__.py index 367e94739..f3e03ae95 100644 --- a/mealie/schema/admin/__init__.py +++ b/mealie/schema/admin/__init__.py @@ -5,49 +5,35 @@ from .debug import DebugResponse from .email import EmailReady, EmailSuccess, EmailTest from .maintenance import MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary from .migration import ChowdownURL, MigrationFile, MigrationImport, Migrations -from .restore import ( - CommentImport, - CustomPageImport, - GroupImport, - ImportBase, - NotificationImport, - RecipeImport, - SettingsImport, - UserImport, -) -from .settings import CustomPageBase, CustomPageOut +from .restore import CommentImport, GroupImport, ImportBase, RecipeImport, SettingsImport, UserImport __all__ = [ - "MaintenanceLogs", - "MaintenanceStorageDetails", - "MaintenanceSummary", - "ChowdownURL", - "MigrationFile", - "MigrationImport", - "Migrations", - "CustomPageBase", - "CustomPageOut", - "CommentImport", - "CustomPageImport", - "GroupImport", - "ImportBase", - "NotificationImport", - "RecipeImport", - "SettingsImport", - "UserImport", "AllBackups", "BackupFile", "BackupOptions", "CreateBackup", "ImportJob", + "MaintenanceLogs", + "MaintenanceStorageDetails", + "MaintenanceSummary", "AdminAboutInfo", "AppInfo", "AppStartupInfo", "AppStatistics", "AppTheme", "CheckAppConfig", + "DebugResponse", "EmailReady", "EmailSuccess", "EmailTest", - "DebugResponse", + "ChowdownURL", + "MigrationFile", + "MigrationImport", + "Migrations", + "CommentImport", + "GroupImport", + "ImportBase", + "RecipeImport", + "SettingsImport", + "UserImport", ] diff --git a/mealie/schema/admin/restore.py b/mealie/schema/admin/restore.py index 68b973cf8..bf32fa1b2 100644 --- a/mealie/schema/admin/restore.py +++ b/mealie/schema/admin/restore.py @@ -25,11 +25,3 @@ class GroupImport(ImportBase): class UserImport(ImportBase): pass - - -class CustomPageImport(ImportBase): - pass - - -class NotificationImport(ImportBase): - pass diff --git a/mealie/schema/admin/settings.py b/mealie/schema/admin/settings.py deleted file mode 100644 index ba884bf4f..000000000 --- a/mealie/schema/admin/settings.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Annotated - -from pydantic import ConfigDict, Field, field_validator -from slugify import slugify - -from mealie.schema._mealie import MealieModel - -from ..recipe.recipe_category import RecipeCategoryResponse - - -class CustomPageBase(MealieModel): - name: str - slug: Annotated[str | None, Field(validate_default=True)] - position: int - categories: list[RecipeCategoryResponse] = [] - model_config = ConfigDict(from_attributes=True) - - @field_validator("slug", mode="before") - def validate_slug(slug: str, values): - name: str = values["name"] - calc_slug: str = slugify(name) - - if slug != calc_slug: - slug = calc_slug - - return slug - - -class CustomPageOut(CustomPageBase): - id: int - model_config = ConfigDict(from_attributes=True) diff --git a/mealie/schema/group/__init__.py b/mealie/schema/group/__init__.py index a731b4432..440a3d1d7 100644 --- a/mealie/schema/group/__init__.py +++ b/mealie/schema/group/__init__.py @@ -7,13 +7,13 @@ from .group_seeder import SeederConfig from .group_statistics import GroupStorage __all__ = [ - "GroupDataExport", "CreateGroupPreferences", "ReadGroupPreferences", "UpdateGroupPreferences", - "GroupStorage", + "GroupDataExport", "DataMigrationCreate", "SupportedMigrations", "SeederConfig", "GroupAdminUpdate", + "GroupStorage", ] diff --git a/mealie/schema/household/__init__.py b/mealie/schema/household/__init__.py index 1fcc7bb25..2f54d97b6 100644 --- a/mealie/schema/household/__init__.py +++ b/mealie/schema/household/__init__.py @@ -70,6 +70,15 @@ from .invite_token import CreateInviteToken, EmailInitationResponse, EmailInvita from .webhook import CreateWebhook, ReadWebhook, SaveWebhook, WebhookPagination, WebhookType __all__ = [ + "CreateHouseholdPreferences", + "ReadHouseholdPreferences", + "SaveHouseholdPreferences", + "UpdateHouseholdPreferences", + "CreateWebhook", + "ReadWebhook", + "SaveWebhook", + "WebhookPagination", + "WebhookType", "GroupEventNotifierCreate", "GroupEventNotifierOptions", "GroupEventNotifierOptionsOut", @@ -79,40 +88,7 @@ __all__ = [ "GroupEventNotifierSave", "GroupEventNotifierUpdate", "GroupEventPagination", - "CreateGroupRecipeAction", - "GroupRecipeActionOut", - "GroupRecipeActionPagination", - "GroupRecipeActionPayload", - "GroupRecipeActionType", - "SaveGroupRecipeAction", - "CreateWebhook", - "ReadWebhook", - "SaveWebhook", - "WebhookPagination", - "WebhookType", - "CreateHouseholdPreferences", - "ReadHouseholdPreferences", - "SaveHouseholdPreferences", - "UpdateHouseholdPreferences", - "HouseholdCreate", - "HouseholdInDB", - "HouseholdPagination", - "HouseholdRecipeBase", - "HouseholdRecipeCreate", - "HouseholdRecipeOut", - "HouseholdRecipeSummary", - "HouseholdRecipeUpdate", - "HouseholdSave", - "HouseholdSummary", - "HouseholdUserSummary", - "UpdateHousehold", - "UpdateHouseholdAdmin", "HouseholdStatistics", - "CreateInviteToken", - "EmailInitationResponse", - "EmailInvitation", - "ReadInviteToken", - "SaveInviteToken", "ShoppingListAddRecipeParams", "ShoppingListAddRecipeParamsBulk", "ShoppingListCreate", @@ -136,5 +112,29 @@ __all__ = [ "ShoppingListSave", "ShoppingListSummary", "ShoppingListUpdate", + "HouseholdCreate", + "HouseholdInDB", + "HouseholdPagination", + "HouseholdRecipeBase", + "HouseholdRecipeCreate", + "HouseholdRecipeOut", + "HouseholdRecipeSummary", + "HouseholdRecipeUpdate", + "HouseholdSave", + "HouseholdSummary", + "HouseholdUserSummary", + "UpdateHousehold", + "UpdateHouseholdAdmin", + "CreateGroupRecipeAction", + "GroupRecipeActionOut", + "GroupRecipeActionPagination", + "GroupRecipeActionPayload", + "GroupRecipeActionType", + "SaveGroupRecipeAction", + "CreateInviteToken", + "EmailInitationResponse", + "EmailInvitation", + "ReadInviteToken", + "SaveInviteToken", "SetPermissions", ] diff --git a/mealie/schema/meal_plan/__init__.py b/mealie/schema/meal_plan/__init__.py index 639c61ee6..c966469be 100644 --- a/mealie/schema/meal_plan/__init__.py +++ b/mealie/schema/meal_plan/__init__.py @@ -12,9 +12,6 @@ from .plan_rules import PlanRulesCreate, PlanRulesDay, PlanRulesOut, PlanRulesPa from .shopping_list import ListItem, ShoppingListIn, ShoppingListOut __all__ = [ - "ListItem", - "ShoppingListIn", - "ShoppingListOut", "CreatePlanEntry", "CreateRandomEntry", "PlanEntryPagination", @@ -28,4 +25,7 @@ __all__ = [ "PlanRulesPagination", "PlanRulesSave", "PlanRulesType", + "ListItem", + "ShoppingListIn", + "ShoppingListOut", ] diff --git a/mealie/schema/recipe/__init__.py b/mealie/schema/recipe/__init__.py index 473f0660b..0d91b89a4 100644 --- a/mealie/schema/recipe/__init__.py +++ b/mealie/schema/recipe/__init__.py @@ -89,8 +89,27 @@ from .recipe_tool import RecipeToolCreate, RecipeToolOut, RecipeToolResponse, Re from .request_helpers import RecipeDuplicate, RecipeSlug, SlugResponse, UpdateImageResponse __all__ = [ - "IngredientReferences", - "RecipeStep", + "RecipeToolCreate", + "RecipeToolOut", + "RecipeToolResponse", + "RecipeToolSave", + "RecipeTimelineEventCreate", + "RecipeTimelineEventIn", + "RecipeTimelineEventOut", + "RecipeTimelineEventPagination", + "RecipeTimelineEventUpdate", + "TimelineEventImage", + "TimelineEventType", + "RecipeAsset", + "RecipeSettings", + "RecipeShareToken", + "RecipeShareTokenCreate", + "RecipeShareTokenSave", + "RecipeShareTokenSummary", + "RecipeDuplicate", + "RecipeSlug", + "SlugResponse", + "UpdateImageResponse", "RecipeNote", "CategoryBase", "CategoryIn", @@ -102,22 +121,23 @@ __all__ = [ "TagIn", "TagOut", "TagSave", - "RecipeAsset", - "RecipeTimelineEventCreate", - "RecipeTimelineEventIn", - "RecipeTimelineEventOut", - "RecipeTimelineEventPagination", - "RecipeTimelineEventUpdate", - "TimelineEventImage", - "TimelineEventType", - "RecipeSuggestionQuery", - "RecipeSuggestionResponse", - "RecipeSuggestionResponseItem", + "RecipeCommentCreate", + "RecipeCommentOut", + "RecipeCommentPagination", + "RecipeCommentSave", + "RecipeCommentUpdate", + "UserBase", + "AssignCategories", + "AssignSettings", + "AssignTags", + "DeleteRecipes", + "ExportBase", + "ExportRecipes", + "ExportTypes", + "IngredientReferences", + "RecipeStep", + "RecipeImageTypes", "Nutrition", - "RecipeShareToken", - "RecipeShareTokenCreate", - "RecipeShareTokenSave", - "RecipeShareTokenSummary", "CreateIngredientFood", "CreateIngredientFoodAlias", "CreateIngredientUnit", @@ -140,13 +160,9 @@ __all__ = [ "SaveIngredientFood", "SaveIngredientUnit", "UnitFoodBase", - "RecipeCommentCreate", - "RecipeCommentOut", - "RecipeCommentPagination", - "RecipeCommentSave", - "RecipeCommentUpdate", - "UserBase", - "RecipeSettings", + "RecipeSuggestionQuery", + "RecipeSuggestionResponse", + "RecipeSuggestionResponseItem", "CreateRecipe", "CreateRecipeBulk", "CreateRecipeByUrlBulk", @@ -164,20 +180,4 @@ __all__ = [ "ScrapeRecipeBase", "ScrapeRecipeData", "ScrapeRecipeTest", - "AssignCategories", - "AssignSettings", - "AssignTags", - "DeleteRecipes", - "ExportBase", - "ExportRecipes", - "ExportTypes", - "RecipeToolCreate", - "RecipeToolOut", - "RecipeToolResponse", - "RecipeToolSave", - "RecipeImageTypes", - "RecipeDuplicate", - "RecipeSlug", - "SlugResponse", - "UpdateImageResponse", ] diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py index 3863e8f80..c398182da 100644 --- a/mealie/schema/recipe/recipe.py +++ b/mealie/schema/recipe/recipe.py @@ -117,9 +117,9 @@ class RecipeSummary(MealieModel): id: UUID4 | None = None _normalize_search: ClassVar[bool] = True - user_id: UUID4 = Field(default_factory=uuid4, validate_default=True) - household_id: UUID4 = Field(default_factory=uuid4, validate_default=True) - group_id: UUID4 = Field(default_factory=uuid4, validate_default=True) + user_id: Annotated[UUID4, Field(default_factory=uuid4, validate_default=True)] + household_id: Annotated[UUID4, Field(default_factory=uuid4, validate_default=True)] + group_id: Annotated[UUID4, Field(default_factory=uuid4, validate_default=True)] name: str | None = None slug: Annotated[str, Field(validate_default=True)] = "" @@ -134,7 +134,7 @@ class RecipeSummary(MealieModel): perform_time: str | None = None description: str | None = "" - recipe_category: Annotated[list[RecipeCategory] | None, Field(validate_default=True)] | None = [] + recipe_category: Annotated[list[RecipeCategory] | None, Field(validate_default=True)] = [] tags: Annotated[list[RecipeTag] | None, Field(validate_default=True)] = [] tools: list[RecipeTool] = [] rating: float | None = None diff --git a/mealie/schema/response/__init__.py b/mealie/schema/response/__init__.py index c513794c5..07e1c46b8 100644 --- a/mealie/schema/response/__init__.py +++ b/mealie/schema/response/__init__.py @@ -21,6 +21,10 @@ from .responses import ErrorResponse, FileTokenResponse, SuccessResponse from .validation import ValidationResponse __all__ = [ + "ErrorResponse", + "FileTokenResponse", + "SuccessResponse", + "SearchFilter", "LogicalOperator", "QueryFilterBuilder", "QueryFilterBuilderComponent", @@ -28,15 +32,11 @@ __all__ = [ "QueryFilterJSONPart", "RelationalKeyword", "RelationalOperator", - "ValidationResponse", "OrderByNullPosition", "OrderDirection", "PaginationBase", "PaginationQuery", "RecipeSearchQuery", "RequestQuery", - "SearchFilter", - "ErrorResponse", - "FileTokenResponse", - "SuccessResponse", + "ValidationResponse", ] diff --git a/mealie/schema/user/__init__.py b/mealie/schema/user/__init__.py index 76db2ec95..f3c7f03cf 100644 --- a/mealie/schema/user/__init__.py +++ b/mealie/schema/user/__init__.py @@ -38,18 +38,12 @@ from .user_passwords import ( ) __all__ = [ - "ForgotPassword", - "PasswordResetToken", - "PrivatePasswordResetToken", - "ResetPassword", - "SavePasswordResetToken", - "ValidateResetToken", + "CreateUserRegistration", "CredentialsRequest", "CredentialsRequestForm", "Token", "TokenData", "UnlockResults", - "CreateUserRegistration", "ChangePassword", "CreateToken", "DeleteTokenResponse", @@ -75,4 +69,10 @@ __all__ = [ "UserRatings", "UserSummary", "UserSummaryPagination", + "ForgotPassword", + "PasswordResetToken", + "PrivatePasswordResetToken", + "ResetPassword", + "SavePasswordResetToken", + "ValidateResetToken", ]