mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-21 22:13:31 -07:00
Merge branch 'mealie-next' into fix/add-recipe-to-list-cross-household
This commit is contained in:
commit
0917be0ecf
80 changed files with 919 additions and 499 deletions
|
@ -71,6 +71,7 @@ tasks:
|
||||||
desc: run code generators
|
desc: run code generators
|
||||||
cmds:
|
cmds:
|
||||||
- poetry run python dev/code-generation/main.py {{ .CLI_ARGS }}
|
- poetry run python dev/code-generation/main.py {{ .CLI_ARGS }}
|
||||||
|
- task: docs:gen
|
||||||
- task: py:format
|
- task: py:format
|
||||||
|
|
||||||
dev:services:
|
dev:services:
|
||||||
|
|
|
@ -8,8 +8,8 @@ from utils import log
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
template = """// This Code is auto generated by gen_ts_types.py
|
template = """// This Code is auto generated by gen_ts_types.py
|
||||||
{% for name in global %}import {{ name }} from "@/components/global/{{ name }}.vue";
|
{% for name in global %}import type {{ name }} from "@/components/global/{{ name }}.vue";
|
||||||
{% endfor %}{% for name in layout %}import {{ name }} from "@/components/layout/{{ name }}.vue";
|
{% endfor %}{% for name in layout %}import type {{ name }} from "@/components/layout/{{ name }}.vue";
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
declare module "vue" {
|
declare module "vue" {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
###############################################
|
###############################################
|
||||||
# Frontend Build
|
# Frontend Build
|
||||||
###############################################
|
###############################################
|
||||||
FROM node:20@sha256:452293f0e5c9b7075829f2cd0dbd5fcae44d89cf5508b84a17bbe0857dc1a654 \
|
FROM node:20@sha256:572a90df10a58ebb7d3f223d661d964a6c2383a9c2b5763162b4f631c53dc56a \
|
||||||
AS frontend-builder
|
AS frontend-builder
|
||||||
|
|
||||||
WORKDIR /frontend
|
WORKDIR /frontend
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -70,7 +70,7 @@ import RecipeCardSection from "@/components/Domain/Recipe/RecipeCardSection.vue"
|
||||||
import { useCookbookStore } from "~/composables/store/use-cookbook-store";
|
import { useCookbookStore } from "~/composables/store/use-cookbook-store";
|
||||||
import { useCookbook } from "~/composables/use-group-cookbooks";
|
import { useCookbook } from "~/composables/use-group-cookbooks";
|
||||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||||
import type { RecipeCookBook } from "~/lib/api/types/cookbook";
|
import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||||
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
|
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
|
||||||
|
|
||||||
const $auth = useMealieAuth();
|
const $auth = useMealieAuth();
|
||||||
|
@ -100,7 +100,7 @@ const dialogStates = reactive({
|
||||||
edit: false,
|
edit: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const editTarget = ref<RecipeCookBook | null>(null);
|
const editTarget = ref<ReadCookBook | null>(null);
|
||||||
function handleEditCookbook() {
|
function handleEditCookbook() {
|
||||||
dialogStates.edit = true;
|
dialogStates.edit = true;
|
||||||
editTarget.value = book.value;
|
editTarget.value = book.value;
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import type { Composer } from "vue-i18n";
|
import type { Composer } from "vue-i18n";
|
||||||
import { useReadOnlyStore, useStore } from "../partials/use-store-factory";
|
import { useReadOnlyStore, useStore } from "../partials/use-store-factory";
|
||||||
import type { RecipeCookBook } from "~/lib/api/types/cookbook";
|
import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||||
import { usePublicExploreApi, useUserApi } from "~/composables/api";
|
import { usePublicExploreApi, useUserApi } from "~/composables/api";
|
||||||
|
|
||||||
const store: Ref<RecipeCookBook[]> = ref([]);
|
const store: Ref<ReadCookBook[]> = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const publicLoading = ref(false);
|
const publicLoading = ref(false);
|
||||||
|
|
||||||
export const useCookbookStore = function (i18n?: Composer) {
|
export const useCookbookStore = function (i18n?: Composer) {
|
||||||
const api = useUserApi(i18n);
|
const api = useUserApi(i18n);
|
||||||
return useStore<RecipeCookBook>(store, loading, api.cookbooks);
|
return useStore<ReadCookBook>(store, loading, api.cookbooks);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const usePublicCookbookStore = function (groupSlug: string, i18n?: Composer) {
|
export const usePublicCookbookStore = function (groupSlug: string, i18n?: Composer) {
|
||||||
const api = usePublicExploreApi(groupSlug, i18n).explore;
|
const api = usePublicExploreApi(groupSlug, i18n).explore;
|
||||||
return useReadOnlyStore<RecipeCookBook>(store, publicLoading, api.cookbooks);
|
return useReadOnlyStore<ReadCookBook>(store, publicLoading, api.cookbooks);
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nuwe kennisgewing",
|
"new-notification": "Nuwe kennisgewing",
|
||||||
"event-notifiers": "Gebeurteniskennisgewers",
|
"event-notifiers": "Gebeurteniskennisgewers",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (oorgeslaan indien leeg)",
|
"apprise-url-skipped-if-blank": "Apprise URL (oorgeslaan indien leeg)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Aktiveer kennisgewer",
|
"enable-notifier": "Aktiveer kennisgewer",
|
||||||
"what-events": "Op watter gebeurtenisse moet hierdie kennisgewing inteken?",
|
"what-events": "Op watter gebeurtenisse moet hierdie kennisgewing inteken?",
|
||||||
"user-events": "Gebruikersgebeurtenisse",
|
"user-events": "Gebruikersgebeurtenisse",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "إشعار جديد",
|
"new-notification": "إشعار جديد",
|
||||||
"event-notifiers": "إشعار الحدث",
|
"event-notifiers": "إشعار الحدث",
|
||||||
"apprise-url-skipped-if-blank": "الرابط Apprise (يتم تجاهله إذا ما كان فارغً)",
|
"apprise-url-skipped-if-blank": "الرابط Apprise (يتم تجاهله إذا ما كان فارغً)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "تفعيل الإشعارات",
|
"enable-notifier": "تفعيل الإشعارات",
|
||||||
"what-events": "ما هي الأحداث التي يجب على هذا المخدم أن يستجيب لها؟",
|
"what-events": "ما هي الأحداث التي يجب على هذا المخدم أن يستجيب لها؟",
|
||||||
"user-events": "أحداث المستخدمين",
|
"user-events": "أحداث المستخدمين",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Ново известие",
|
"new-notification": "Ново известие",
|
||||||
"event-notifiers": "Известия за събитие",
|
"event-notifiers": "Известия за събитие",
|
||||||
"apprise-url-skipped-if-blank": "URL за известяване (пропуска се ако е празно)",
|
"apprise-url-skipped-if-blank": "URL за известяване (пропуска се ако е празно)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Включи известията",
|
"enable-notifier": "Включи известията",
|
||||||
"what-events": "За кои събития трябва да се получават известия?",
|
"what-events": "За кои събития трябва да се получават известия?",
|
||||||
"user-events": "Потребителски събития",
|
"user-events": "Потребителски събития",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nova notificació",
|
"new-notification": "Nova notificació",
|
||||||
"event-notifiers": "Notificacions d'esdeveniments",
|
"event-notifiers": "Notificacions d'esdeveniments",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (si es deixa buit, s'ignorarà)",
|
"apprise-url-skipped-if-blank": "Apprise URL (si es deixa buit, s'ignorarà)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Habilita la notificació",
|
"enable-notifier": "Habilita la notificació",
|
||||||
"what-events": "Què esdeveniments vols que utilitzen aquest notificador?",
|
"what-events": "Què esdeveniments vols que utilitzen aquest notificador?",
|
||||||
"user-events": "Esdeveniments d'usuari",
|
"user-events": "Esdeveniments d'usuari",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nové oznámení",
|
"new-notification": "Nové oznámení",
|
||||||
"event-notifiers": "Notifikace událostí",
|
"event-notifiers": "Notifikace událostí",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (přeskočeno pokud je prázdné)",
|
"apprise-url-skipped-if-blank": "Apprise URL (přeskočeno pokud je prázdné)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Povolit notifikaci",
|
"enable-notifier": "Povolit notifikaci",
|
||||||
"what-events": "K jakým událostem by se měl tento oznamovatel přihlásit?",
|
"what-events": "K jakým událostem by se měl tento oznamovatel přihlásit?",
|
||||||
"user-events": "Uživatelské události",
|
"user-events": "Uživatelské události",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Ny notifikation",
|
"new-notification": "Ny notifikation",
|
||||||
"event-notifiers": "Notifikation om begivenheder",
|
"event-notifiers": "Notifikation om begivenheder",
|
||||||
"apprise-url-skipped-if-blank": "Informations link (sprunget over hvis ladet være tomt)",
|
"apprise-url-skipped-if-blank": "Informations link (sprunget over hvis ladet være tomt)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Aktiver Notifikationer",
|
"enable-notifier": "Aktiver Notifikationer",
|
||||||
"what-events": "Hvilke begivenheder skal denne anmelder abonnere på?",
|
"what-events": "Hvilke begivenheder skal denne anmelder abonnere på?",
|
||||||
"user-events": "Brugerhændelser",
|
"user-events": "Brugerhændelser",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Neue Benachrichtigung",
|
"new-notification": "Neue Benachrichtigung",
|
||||||
"event-notifiers": "Ereignis-Benachrichtigungen",
|
"event-notifiers": "Ereignis-Benachrichtigungen",
|
||||||
"apprise-url-skipped-if-blank": "Apprise-URL (wird übersprungen, wenn leer)",
|
"apprise-url-skipped-if-blank": "Apprise-URL (wird übersprungen, wenn leer)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Benachrichtigen aktivieren",
|
"enable-notifier": "Benachrichtigen aktivieren",
|
||||||
"what-events": "Welche Ereignisse soll diese Benachrichtigung abonnieren?",
|
"what-events": "Welche Ereignisse soll diese Benachrichtigung abonnieren?",
|
||||||
"user-events": "Benutzer-Ereignisse",
|
"user-events": "Benutzer-Ereignisse",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Νέα ειδοποίηση",
|
"new-notification": "Νέα ειδοποίηση",
|
||||||
"event-notifiers": "Ειδοποιητές Συμβάντος",
|
"event-notifiers": "Ειδοποιητές Συμβάντος",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (παραλείπεται αν είναι κενό)",
|
"apprise-url-skipped-if-blank": "Apprise URL (παραλείπεται αν είναι κενό)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Δεδομένου ότι οι διευθύνσεις URL Apprise περιέχουν συνήθως ευαίσθητες πληροφορίες, το πεδίο αυτό παραμένει σκόπιμα κενό κατά την επεξεργασία. Αν θέλετε να ενημερώσετε το URL, παρακαλώ εισάγετε το νέο εδώ, αλλιώς αφήστε το κενό για να διατηρήσετε την τρέχουσα διεύθυνση URL.",
|
||||||
"enable-notifier": "Ενεργοποίηση ειδοποιητή",
|
"enable-notifier": "Ενεργοποίηση ειδοποιητή",
|
||||||
"what-events": "Σε ποια συμβάντα θα πρέπει να εγγραφεί αυτός ο ειδοποιητής;",
|
"what-events": "Σε ποια συμβάντα θα πρέπει να εγγραφεί αυτός ο ειδοποιητής;",
|
||||||
"user-events": "Συμβάντα Χρήστη",
|
"user-events": "Συμβάντα Χρήστη",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "New Notification",
|
"new-notification": "New Notification",
|
||||||
"event-notifiers": "Event Notifiers",
|
"event-notifiers": "Event Notifiers",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (skipped if blank)",
|
"apprise-url-skipped-if-blank": "Apprise URL (skipped if blank)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Enable Notifier",
|
"enable-notifier": "Enable Notifier",
|
||||||
"what-events": "What events should this notifier subscribe to?",
|
"what-events": "What events should this notifier subscribe to?",
|
||||||
"user-events": "User Events",
|
"user-events": "User Events",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nueva notificación",
|
"new-notification": "Nueva notificación",
|
||||||
"event-notifiers": "Notificaciones de eventos",
|
"event-notifiers": "Notificaciones de eventos",
|
||||||
"apprise-url-skipped-if-blank": "URL de Apprise (omitida si está en blanco)",
|
"apprise-url-skipped-if-blank": "URL de Apprise (omitida si está en blanco)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Habilitar notificador",
|
"enable-notifier": "Habilitar notificador",
|
||||||
"what-events": "¿A qué eventos debe suscribirse este notificador?",
|
"what-events": "¿A qué eventos debe suscribirse este notificador?",
|
||||||
"user-events": "Eventos de los usuarios",
|
"user-events": "Eventos de los usuarios",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Uus teade",
|
"new-notification": "Uus teade",
|
||||||
"event-notifiers": "Sündmuste märguanded",
|
"event-notifiers": "Sündmuste märguanded",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (kui on tühi, jäetakse vahele)",
|
"apprise-url-skipped-if-blank": "Apprise URL (kui on tühi, jäetakse vahele)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Luba teavitaja",
|
"enable-notifier": "Luba teavitaja",
|
||||||
"what-events": "Millised sündmused peaks see teavitaja tellimaa?",
|
"what-events": "Millised sündmused peaks see teavitaja tellimaa?",
|
||||||
"user-events": "Kasutaja sündmused",
|
"user-events": "Kasutaja sündmused",
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
"category-events": "Kategooria sündmused",
|
"category-events": "Kategooria sündmused",
|
||||||
"when-a-new-user-joins-your-group": "Kui uus kasutaja liitub sinu grupiga",
|
"when-a-new-user-joins-your-group": "Kui uus kasutaja liitub sinu grupiga",
|
||||||
"recipe-events": "Retsepti sündmused",
|
"recipe-events": "Retsepti sündmused",
|
||||||
"label-events": "Label Events"
|
"label-events": "Sildista sündmused"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"add": "Lisa",
|
"add": "Lisa",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Uusi ilmoitus",
|
"new-notification": "Uusi ilmoitus",
|
||||||
"event-notifiers": "Tapahtumien ilmoitukset",
|
"event-notifiers": "Tapahtumien ilmoitukset",
|
||||||
"apprise-url-skipped-if-blank": "Ilmoitusverkko-osoite (voi jättää tyhjäksi)",
|
"apprise-url-skipped-if-blank": "Ilmoitusverkko-osoite (voi jättää tyhjäksi)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Ota ilmoittaja käyttöön",
|
"enable-notifier": "Ota ilmoittaja käyttöön",
|
||||||
"what-events": "Mistä tapahtumista tulisi ilmoittaa?",
|
"what-events": "Mistä tapahtumista tulisi ilmoittaa?",
|
||||||
"user-events": "Käyttäjän tapahtumat",
|
"user-events": "Käyttäjän tapahtumat",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nouvelle notification",
|
"new-notification": "Nouvelle notification",
|
||||||
"event-notifiers": "Notifications d'événements",
|
"event-notifiers": "Notifications d'événements",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activer la notification",
|
"enable-notifier": "Activer la notification",
|
||||||
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
||||||
"user-events": "Evénements utilisateur",
|
"user-events": "Evénements utilisateur",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nouvelle notification",
|
"new-notification": "Nouvelle notification",
|
||||||
"event-notifiers": "Notifications d'événements",
|
"event-notifiers": "Notifications d'événements",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activer la notification",
|
"enable-notifier": "Activer la notification",
|
||||||
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
||||||
"user-events": "Événements de l'utilisateur",
|
"user-events": "Événements de l'utilisateur",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nouvelle notification",
|
"new-notification": "Nouvelle notification",
|
||||||
"event-notifiers": "Notifications d'événements",
|
"event-notifiers": "Notifications d'événements",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
"apprise-url-skipped-if-blank": "URL Apprise (ignoré si vide)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activer la notification",
|
"enable-notifier": "Activer la notification",
|
||||||
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
"what-events": "À quels événements cette notification doit-elle s'abonner ?",
|
||||||
"user-events": "Événements utilisateur",
|
"user-events": "Événements utilisateur",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nova Notificación",
|
"new-notification": "Nova Notificación",
|
||||||
"event-notifiers": "Notificadores de Eventos",
|
"event-notifiers": "Notificadores de Eventos",
|
||||||
"apprise-url-skipped-if-blank": "URL de Apprise (omitido se está en branco)",
|
"apprise-url-skipped-if-blank": "URL de Apprise (omitido se está en branco)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activar o Notificador",
|
"enable-notifier": "Activar o Notificador",
|
||||||
"what-events": "A que eventos debería subscribirse este notificador?",
|
"what-events": "A que eventos debería subscribirse este notificador?",
|
||||||
"user-events": "Eventos de Usuario",
|
"user-events": "Eventos de Usuario",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "התראה חדשה",
|
"new-notification": "התראה חדשה",
|
||||||
"event-notifiers": "מנגנוני התרעה על אירועים",
|
"event-notifiers": "מנגנוני התרעה על אירועים",
|
||||||
"apprise-url-skipped-if-blank": "כתובת Apprise (דלג אם ריק)",
|
"apprise-url-skipped-if-blank": "כתובת Apprise (דלג אם ריק)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "הפעלת מתריע",
|
"enable-notifier": "הפעלת מתריע",
|
||||||
"what-events": "לאילו אירועים לרשום את מתריע זה?",
|
"what-events": "לאילו אירועים לרשום את מתריע זה?",
|
||||||
"user-events": "אירועי משתמש",
|
"user-events": "אירועי משתמש",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nova Obavijest",
|
"new-notification": "Nova Obavijest",
|
||||||
"event-notifiers": "Obavještavatelji Događaja",
|
"event-notifiers": "Obavještavatelji Događaja",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (preskočeno ako je prazno)",
|
"apprise-url-skipped-if-blank": "Apprise URL (preskočeno ako je prazno)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Omogući obavještavanje",
|
"enable-notifier": "Omogući obavještavanje",
|
||||||
"what-events": "Na koje događaje bi ovaj obavještavatelj trebao biti pretplaćen?",
|
"what-events": "Na koje događaje bi ovaj obavještavatelj trebao biti pretplaćen?",
|
||||||
"user-events": "Događaji Korisnika",
|
"user-events": "Događaji Korisnika",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Új értesítés",
|
"new-notification": "Új értesítés",
|
||||||
"event-notifiers": "Esemény értesítők",
|
"event-notifiers": "Esemény értesítők",
|
||||||
"apprise-url-skipped-if-blank": "Értesítendő URL (kihagy, ha üres)",
|
"apprise-url-skipped-if-blank": "Értesítendő URL (kihagy, ha üres)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Értesítés engedélyezése",
|
"enable-notifier": "Értesítés engedélyezése",
|
||||||
"what-events": "Milyen eseményekre figyeljen ez az értesítés?",
|
"what-events": "Milyen eseményekre figyeljen ez az értesítés?",
|
||||||
"user-events": "Felhasználói Események",
|
"user-events": "Felhasználói Események",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Ný tilkynning",
|
"new-notification": "Ný tilkynning",
|
||||||
"event-notifiers": "Viðburðar tilkynningar",
|
"event-notifiers": "Viðburðar tilkynningar",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (sleppt ef tómt)",
|
"apprise-url-skipped-if-blank": "Apprise URL (sleppt ef tómt)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Virkja tilkynningar",
|
"enable-notifier": "Virkja tilkynningar",
|
||||||
"what-events": "Hvaða viðburði ætti þessi tilkynnir að vera áskrifandi að?",
|
"what-events": "Hvaða viðburði ætti þessi tilkynnir að vera áskrifandi að?",
|
||||||
"user-events": "Notenda viðburðir",
|
"user-events": "Notenda viðburðir",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nuova Notifica",
|
"new-notification": "Nuova Notifica",
|
||||||
"event-notifiers": "Notifiche Evento",
|
"event-notifiers": "Notifiche Evento",
|
||||||
"apprise-url-skipped-if-blank": "Url di Apprise (ignorato se vuoto)",
|
"apprise-url-skipped-if-blank": "Url di Apprise (ignorato se vuoto)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Poiché gli URL Apprise contengono in genere informazioni sensibili, questo campo viene lasciato intenzionalmente vuoto durante la modifica. Se si desidera aggiornare l'URL, inserire qui il nuovo URL, altrimenti lasciarlo vuoto per mantenere l'URL corrente.",
|
||||||
"enable-notifier": "Abilita Notificatore",
|
"enable-notifier": "Abilita Notificatore",
|
||||||
"what-events": "Quali eventi dovrebbe sottoscrivere questo notificatore?",
|
"what-events": "Quali eventi dovrebbe sottoscrivere questo notificatore?",
|
||||||
"user-events": "Eventi Utente",
|
"user-events": "Eventi Utente",
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
"category-events": "Categoria Eventi",
|
"category-events": "Categoria Eventi",
|
||||||
"when-a-new-user-joins-your-group": "Quando un nuovo utente entra nel tuo gruppo",
|
"when-a-new-user-joins-your-group": "Quando un nuovo utente entra nel tuo gruppo",
|
||||||
"recipe-events": "Eventi di ricette",
|
"recipe-events": "Eventi di ricette",
|
||||||
"label-events": "Label Events"
|
"label-events": "Eventi Etichetta"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"add": "Aggiungi",
|
"add": "Aggiungi",
|
||||||
|
@ -473,7 +474,7 @@
|
||||||
"comment": "Commento",
|
"comment": "Commento",
|
||||||
"comments": "Commenti",
|
"comments": "Commenti",
|
||||||
"delete-confirmation": "Sei sicuro di voler eliminare questa ricetta?",
|
"delete-confirmation": "Sei sicuro di voler eliminare questa ricetta?",
|
||||||
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
|
"admin-delete-confirmation": "Stai per eliminare una ricetta che non è tua usando i permessi di amministrazione. Sei sicuro?",
|
||||||
"delete-recipe": "Elimina Ricetta",
|
"delete-recipe": "Elimina Ricetta",
|
||||||
"description": "Descrizione",
|
"description": "Descrizione",
|
||||||
"disable-amount": "Disabilita Quantità Ingredienti",
|
"disable-amount": "Disabilita Quantità Ingredienti",
|
||||||
|
@ -581,10 +582,10 @@
|
||||||
"made-this": "L'Ho Preparato",
|
"made-this": "L'Ho Preparato",
|
||||||
"how-did-it-turn-out": "Come è venuto?",
|
"how-did-it-turn-out": "Come è venuto?",
|
||||||
"user-made-this": "{user} l'ha preparato",
|
"user-made-this": "{user} l'ha preparato",
|
||||||
"added-to-timeline": "Added to timeline",
|
"added-to-timeline": "Aggiunto alla cronologia",
|
||||||
"failed-to-add-to-timeline": "Failed to add to timeline",
|
"failed-to-add-to-timeline": "Impossibile aggiungere alla cronologia",
|
||||||
"failed-to-update-recipe": "Failed to update recipe",
|
"failed-to-update-recipe": "Impossibile aggiornare la ricetta",
|
||||||
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
|
"added-to-timeline-but-failed-to-add-image": "Aggiunto alla cronologia, ma non è stato possibile aggiungere l'immagine",
|
||||||
"api-extras-description": "Le opzioni extra delle ricette sono una caratteristica fondamentale dell'API Mealie. Consentono di creare json personalizzati con coppie di chiavi/valore all'interno di una ricetta a cui fare riferimento tramite applicazioni terze. È possibile utilizzare queste chiavi per inserire informazioni, per esempio per attivare automazioni oppure per inoltrare messaggi personalizzati al dispositivo desiderato.",
|
"api-extras-description": "Le opzioni extra delle ricette sono una caratteristica fondamentale dell'API Mealie. Consentono di creare json personalizzati con coppie di chiavi/valore all'interno di una ricetta a cui fare riferimento tramite applicazioni terze. È possibile utilizzare queste chiavi per inserire informazioni, per esempio per attivare automazioni oppure per inoltrare messaggi personalizzati al dispositivo desiderato.",
|
||||||
"message-key": "Chiave Messaggio",
|
"message-key": "Chiave Messaggio",
|
||||||
"parse": "Analizza",
|
"parse": "Analizza",
|
||||||
|
@ -606,10 +607,10 @@
|
||||||
"create-recipe-from-an-image": "Crea ricetta da un'immagine",
|
"create-recipe-from-an-image": "Crea ricetta da un'immagine",
|
||||||
"create-recipe-from-an-image-description": "Crea una ricetta caricando un'immagine di essa. Mealie tenterà di estrarre il testo dall'immagine usando l'IA e creare una ricetta da esso.",
|
"create-recipe-from-an-image-description": "Crea una ricetta caricando un'immagine di essa. Mealie tenterà di estrarre il testo dall'immagine usando l'IA e creare una ricetta da esso.",
|
||||||
"crop-and-rotate-the-image": "Ritaglia e ruota l'immagine in modo che solo il testo sia visibile e che sia orientato correttamente.",
|
"crop-and-rotate-the-image": "Ritaglia e ruota l'immagine in modo che solo il testo sia visibile e che sia orientato correttamente.",
|
||||||
"create-from-images": "Create from Images",
|
"create-from-images": "Crea da immagini",
|
||||||
"should-translate-description": "Traduci la ricetta nella mia lingua",
|
"should-translate-description": "Traduci la ricetta nella mia lingua",
|
||||||
"please-wait-image-procesing": "Attendere, l'immagine è in fase di elaborazione. Potrebbe volerci un po' di tempo.",
|
"please-wait-image-procesing": "Attendere, l'immagine è in fase di elaborazione. Potrebbe volerci un po' di tempo.",
|
||||||
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
|
"please-wait-images-processing": "Attendere, le immagini sono in fase di elaborazione. Potrebbe volerci un po' di tempo.",
|
||||||
"bulk-url-import": "Importazione multipla URL",
|
"bulk-url-import": "Importazione multipla URL",
|
||||||
"debug-scraper": "Debug Scraper",
|
"debug-scraper": "Debug Scraper",
|
||||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Crea una ricetta fornendo il nome. Tutte le ricette devono avere nomi univoci.",
|
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Crea una ricetta fornendo il nome. Tutte le ricette devono avere nomi univoci.",
|
||||||
|
@ -665,17 +666,17 @@
|
||||||
"no-unit": "Nessuna unità",
|
"no-unit": "Nessuna unità",
|
||||||
"missing-unit": "Crea unità mancante: {unit}",
|
"missing-unit": "Crea unità mancante: {unit}",
|
||||||
"missing-food": "Crea cibo mancante: {food}",
|
"missing-food": "Crea cibo mancante: {food}",
|
||||||
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
|
"this-unit-could-not-be-parsed-automatically": "Questa unità non può essere analizzata automaticamente",
|
||||||
"this-food-could-not-be-parsed-automatically": "This food could not be parsed automatically",
|
"this-food-could-not-be-parsed-automatically": "Questo alimento non può essere analizzato automaticamente",
|
||||||
"no-food": "Nessun Alimento"
|
"no-food": "Nessun Alimento"
|
||||||
},
|
},
|
||||||
"reset-servings-count": "Reimposta conteggio porzioni",
|
"reset-servings-count": "Reimposta conteggio porzioni",
|
||||||
"not-linked-ingredients": "Ingredienti Aggiuntivi",
|
"not-linked-ingredients": "Ingredienti Aggiuntivi",
|
||||||
"upload-another-image": "Upload another image",
|
"upload-another-image": "Carica un'altra immagine",
|
||||||
"upload-images": "Upload images",
|
"upload-images": "Carica immagini",
|
||||||
"upload-more-images": "Upload more images",
|
"upload-more-images": "Carica altre immagini",
|
||||||
"set-as-cover-image": "Set as recipe cover image",
|
"set-as-cover-image": "Imposta come immagine di copertina della ricetta",
|
||||||
"cover-image": "Cover image"
|
"cover-image": "Immagine di copertina"
|
||||||
},
|
},
|
||||||
"recipe-finder": {
|
"recipe-finder": {
|
||||||
"recipe-finder": "Trova ricette",
|
"recipe-finder": "Trova ricette",
|
||||||
|
@ -1168,7 +1169,7 @@
|
||||||
"group-details": "Dettagli Gruppo",
|
"group-details": "Dettagli Gruppo",
|
||||||
"group-details-description": "Prima di creare un account, è necessario creare un gruppo. Il gruppo conterrà solo voi, ma potrete invitare altre persone in seguito. I membri del gruppo possono condividere piani alimentari, liste della spesa, ricette e molto altro!",
|
"group-details-description": "Prima di creare un account, è necessario creare un gruppo. Il gruppo conterrà solo voi, ma potrete invitare altre persone in seguito. I membri del gruppo possono condividere piani alimentari, liste della spesa, ricette e molto altro!",
|
||||||
"use-seed-data": "Utilizzo Dati Generati",
|
"use-seed-data": "Utilizzo Dati Generati",
|
||||||
"use-seed-data-description": "Mealie ships with a collection of Foods, Units, and Labels that can be used to populate your group with helpful data for organizing your recipes. These are translated into the language you currently have selected. You can always add to or modify this data later.",
|
"use-seed-data-description": "Mealie include una raccolta di Alimenti, Unità ed Etichette che possono essere utilizzate per arricchire il proprio gruppo con dati utili per organizzare le proprie ricette. Questi dati vengono tradotti nella lingua selezionata. Si può sempre aggiungere o modificare questi dati in seguito.",
|
||||||
"account-details": "Dettagli dell'Account"
|
"account-details": "Dettagli dell'Account"
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "新着通知",
|
"new-notification": "新着通知",
|
||||||
"event-notifiers": "イベント通知",
|
"event-notifiers": "イベント通知",
|
||||||
"apprise-url-skipped-if-blank": "通知用URL (空欄の場合はスキップ)",
|
"apprise-url-skipped-if-blank": "通知用URL (空欄の場合はスキップ)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "通知を有効にする",
|
"enable-notifier": "通知を有効にする",
|
||||||
"what-events": "この通知はどのイベントを購読すべきですか?",
|
"what-events": "この通知はどのイベントを購読すべきですか?",
|
||||||
"user-events": "ユーザーイベント",
|
"user-events": "ユーザーイベント",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "새 알림",
|
"new-notification": "새 알림",
|
||||||
"event-notifiers": "이벤트 알림이",
|
"event-notifiers": "이벤트 알림이",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (비워두면 생략합니다)",
|
"apprise-url-skipped-if-blank": "Apprise URL (비워두면 생략합니다)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "알림 활성화",
|
"enable-notifier": "알림 활성화",
|
||||||
"what-events": "이 알리미는 어떤 이벤트를 구독해야 합니까?",
|
"what-events": "이 알리미는 어떤 이벤트를 구독해야 합니까?",
|
||||||
"user-events": "사용자 이벤트",
|
"user-events": "사용자 이벤트",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Naujas pranešimas",
|
"new-notification": "Naujas pranešimas",
|
||||||
"event-notifiers": "Įvykių pranešimai",
|
"event-notifiers": "Įvykių pranešimai",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (praleidžiama, jei tuščia)",
|
"apprise-url-skipped-if-blank": "Apprise URL (praleidžiama, jei tuščia)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Įjungti pranešiklį",
|
"enable-notifier": "Įjungti pranešiklį",
|
||||||
"what-events": "Kokie įvykiai turėtų būti sekami?",
|
"what-events": "Kokie įvykiai turėtų būti sekami?",
|
||||||
"user-events": "Naudotojų įvykiai",
|
"user-events": "Naudotojų įvykiai",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Jauns paziņojums",
|
"new-notification": "Jauns paziņojums",
|
||||||
"event-notifiers": "Notikumu paziņotāji",
|
"event-notifiers": "Notikumu paziņotāji",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (izlaists, ja tukšs)",
|
"apprise-url-skipped-if-blank": "Apprise URL (izlaists, ja tukšs)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Iespējot paziņotāju",
|
"enable-notifier": "Iespējot paziņotāju",
|
||||||
"what-events": "Kādus notikumus šim paziņotājam vajadzētu abonēt?",
|
"what-events": "Kādus notikumus šim paziņotājam vajadzētu abonēt?",
|
||||||
"user-events": "Lietotāju notikumi",
|
"user-events": "Lietotāju notikumi",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nieuwe melding",
|
"new-notification": "Nieuwe melding",
|
||||||
"event-notifiers": "Meldingen van gebeurtenissen",
|
"event-notifiers": "Meldingen van gebeurtenissen",
|
||||||
"apprise-url-skipped-if-blank": "URL van Apprise (overgeslagen als veld leeg is)",
|
"apprise-url-skipped-if-blank": "URL van Apprise (overgeslagen als veld leeg is)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activeer melding",
|
"enable-notifier": "Activeer melding",
|
||||||
"what-events": "Op welke gebeurtenissen moet deze melding zich abonneren?",
|
"what-events": "Op welke gebeurtenissen moet deze melding zich abonneren?",
|
||||||
"user-events": "Gebeurtenissen van gebruiker",
|
"user-events": "Gebeurtenissen van gebruiker",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nytt varsel",
|
"new-notification": "Nytt varsel",
|
||||||
"event-notifiers": "Hendelsesvarsler",
|
"event-notifiers": "Hendelsesvarsler",
|
||||||
"apprise-url-skipped-if-blank": "Apprise-URL (hoppes over hvis tom)",
|
"apprise-url-skipped-if-blank": "Apprise-URL (hoppes over hvis tom)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Aktiver varslingsagenten",
|
"enable-notifier": "Aktiver varslingsagenten",
|
||||||
"what-events": "Hvilke hendelser skal denne varslingsagenten abonnere på?",
|
"what-events": "Hvilke hendelser skal denne varslingsagenten abonnere på?",
|
||||||
"user-events": "Brukerhendelser",
|
"user-events": "Brukerhendelser",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nowe powiadomienie",
|
"new-notification": "Nowe powiadomienie",
|
||||||
"event-notifiers": "Powiadomienia o zdarzeniach",
|
"event-notifiers": "Powiadomienia o zdarzeniach",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (pominięty, jeśli puste)",
|
"apprise-url-skipped-if-blank": "URL Apprise (pominięty, jeśli puste)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Ponieważ adresy URL Apprise zawierają zazwyczaj poufne informacje, pole to pozostaje celowo puste podczas edycji. Jeśli chcesz zaktualizować adres URL, wprowadź ten nowy tutaj, w przeciwnym razie pozostaw puste, aby zachować bieżący adres URL.",
|
||||||
"enable-notifier": "Włącz Powiadomienie",
|
"enable-notifier": "Włącz Powiadomienie",
|
||||||
"what-events": "Jakie zdarzenia powinien subskrybować ten powiadamiający?",
|
"what-events": "Jakie zdarzenia powinien subskrybować ten powiadamiający?",
|
||||||
"user-events": "Zdarzenia użytkownika",
|
"user-events": "Zdarzenia użytkownika",
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
"category-events": "Wydarzenia kategorii",
|
"category-events": "Wydarzenia kategorii",
|
||||||
"when-a-new-user-joins-your-group": "Kiedy nowy użytkownik dołączy do Twojej grupy",
|
"when-a-new-user-joins-your-group": "Kiedy nowy użytkownik dołączy do Twojej grupy",
|
||||||
"recipe-events": "Zdarzenia Przepisów",
|
"recipe-events": "Zdarzenia Przepisów",
|
||||||
"label-events": "Label Events"
|
"label-events": "Etykieta wydarzeń"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"add": "Dodaj",
|
"add": "Dodaj",
|
||||||
|
@ -674,8 +675,8 @@
|
||||||
"upload-another-image": "Prześlij kolejny obraz",
|
"upload-another-image": "Prześlij kolejny obraz",
|
||||||
"upload-images": "Prześlij obraz",
|
"upload-images": "Prześlij obraz",
|
||||||
"upload-more-images": "Prześlij więcej obrazów",
|
"upload-more-images": "Prześlij więcej obrazów",
|
||||||
"set-as-cover-image": "Set as recipe cover image",
|
"set-as-cover-image": "Ustaw jako okładkę przepisu",
|
||||||
"cover-image": "Cover image"
|
"cover-image": "Okładka"
|
||||||
},
|
},
|
||||||
"recipe-finder": {
|
"recipe-finder": {
|
||||||
"recipe-finder": "Wyszukiwarka przepisów",
|
"recipe-finder": "Wyszukiwarka przepisów",
|
||||||
|
@ -1168,7 +1169,7 @@
|
||||||
"group-details": "Szczegóły grupy",
|
"group-details": "Szczegóły grupy",
|
||||||
"group-details-description": "Zanim utworzysz konto musisz stworzyć grupę. Twoja grupa zawierać będzie tylko Ciebie, ale będziesz istniała możlwiość zaproszenia do niej innych. Użytkownicy Twojej grupy mogą współdzielić plany posiłków, listy zakupów, przepisy i więcej!",
|
"group-details-description": "Zanim utworzysz konto musisz stworzyć grupę. Twoja grupa zawierać będzie tylko Ciebie, ale będziesz istniała możlwiość zaproszenia do niej innych. Użytkownicy Twojej grupy mogą współdzielić plany posiłków, listy zakupów, przepisy i więcej!",
|
||||||
"use-seed-data": "Użyj przykładowych danych",
|
"use-seed-data": "Użyj przykładowych danych",
|
||||||
"use-seed-data-description": "Mealie ships with a collection of Foods, Units, and Labels that can be used to populate your group with helpful data for organizing your recipes. These are translated into the language you currently have selected. You can always add to or modify this data later.",
|
"use-seed-data-description": "Wysyłka posiłków z kolekcją żywności, jednostek i etykiet, które mogą być użyte do wypełnienia Twojej grupy pomocnymi danymi do organizacji twoich przepisów. Są one tłumaczone na wybrany język. Zawsze możesz dodać lub zmodyfikować te dane później.",
|
||||||
"account-details": "Szczegóły konta"
|
"account-details": "Szczegóły konta"
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nova Notificação",
|
"new-notification": "Nova Notificação",
|
||||||
"event-notifiers": "Notificações de Eventos",
|
"event-notifiers": "Notificações de Eventos",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (ignorado se estiver em branco)",
|
"apprise-url-skipped-if-blank": "URL Apprise (ignorado se estiver em branco)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Habilitar Notificador",
|
"enable-notifier": "Habilitar Notificador",
|
||||||
"what-events": "A quais eventos este notificador deve subscrever?",
|
"what-events": "A quais eventos este notificador deve subscrever?",
|
||||||
"user-events": "Eventos do usuário",
|
"user-events": "Eventos do usuário",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nova Notificação",
|
"new-notification": "Nova Notificação",
|
||||||
"event-notifiers": "Notificadores de eventos",
|
"event-notifiers": "Notificadores de eventos",
|
||||||
"apprise-url-skipped-if-blank": "URL da Apprise (ignorado se vazio)",
|
"apprise-url-skipped-if-blank": "URL da Apprise (ignorado se vazio)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Ativar Notificador",
|
"enable-notifier": "Ativar Notificador",
|
||||||
"what-events": "Que eventos este notificador deve subscrever?",
|
"what-events": "Que eventos este notificador deve subscrever?",
|
||||||
"user-events": "Eventos do utilizador",
|
"user-events": "Eventos do utilizador",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Notificare nouă",
|
"new-notification": "Notificare nouă",
|
||||||
"event-notifiers": "Notificatori de evenimente",
|
"event-notifiers": "Notificatori de evenimente",
|
||||||
"apprise-url-skipped-if-blank": "URL Apprise (ignorat daca e gol)",
|
"apprise-url-skipped-if-blank": "URL Apprise (ignorat daca e gol)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Activare notificator",
|
"enable-notifier": "Activare notificator",
|
||||||
"what-events": "La ce evenimente ar trebui să se înscrie acest notificator?",
|
"what-events": "La ce evenimente ar trebui să se înscrie acest notificator?",
|
||||||
"user-events": "Evenimente Utilizator",
|
"user-events": "Evenimente Utilizator",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Новое уведомление",
|
"new-notification": "Новое уведомление",
|
||||||
"event-notifiers": "Уведомления о событии",
|
"event-notifiers": "Уведомления о событии",
|
||||||
"apprise-url-skipped-if-blank": "URL-адрес (пропущен, если пусто)",
|
"apprise-url-skipped-if-blank": "URL-адрес (пропущен, если пусто)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Включить уведомления",
|
"enable-notifier": "Включить уведомления",
|
||||||
"what-events": "На какие события следует настроить уведомления?",
|
"what-events": "На какие события следует настроить уведомления?",
|
||||||
"user-events": "События пользователя",
|
"user-events": "События пользователя",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Nové upozornenie",
|
"new-notification": "Nové upozornenie",
|
||||||
"event-notifiers": "Upozornenia udalostí",
|
"event-notifiers": "Upozornenia udalostí",
|
||||||
"apprise-url-skipped-if-blank": "Informačná URL (preskočená, ak je prázdna)",
|
"apprise-url-skipped-if-blank": "Informačná URL (preskočená, ak je prázdna)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Zapnúť notifikátor",
|
"enable-notifier": "Zapnúť notifikátor",
|
||||||
"what-events": "Pre ktoré udalosti si želáte zapnúť notifikátor?",
|
"what-events": "Pre ktoré udalosti si želáte zapnúť notifikátor?",
|
||||||
"user-events": "Udalosti používateľa",
|
"user-events": "Udalosti používateľa",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Novo obvestilo",
|
"new-notification": "Novo obvestilo",
|
||||||
"event-notifiers": "Obvestila o dogodkih",
|
"event-notifiers": "Obvestila o dogodkih",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (preskočeno, če je prazno)",
|
"apprise-url-skipped-if-blank": "Apprise URL (preskočeno, če je prazno)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Vključi obvestila",
|
"enable-notifier": "Vključi obvestila",
|
||||||
"what-events": "Katere dogodke naj spremlja obveščevalni sistem?",
|
"what-events": "Katere dogodke naj spremlja obveščevalni sistem?",
|
||||||
"user-events": "Dogodki uporabnika",
|
"user-events": "Dogodki uporabnika",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Ново обавештење",
|
"new-notification": "Ново обавештење",
|
||||||
"event-notifiers": "Обавештавач о догађају",
|
"event-notifiers": "Обавештавач о догађају",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (прескочено ако је празно)",
|
"apprise-url-skipped-if-blank": "Apprise URL (прескочено ако је празно)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Омогући обавештење",
|
"enable-notifier": "Омогући обавештење",
|
||||||
"what-events": "На које догађаје би требао да се претплати овај обавештавач?",
|
"what-events": "На које догађаје би требао да се претплати овај обавештавач?",
|
||||||
"user-events": "Догађаји корисника",
|
"user-events": "Догађаји корисника",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Ny avisering",
|
"new-notification": "Ny avisering",
|
||||||
"event-notifiers": "Händelseavisering",
|
"event-notifiers": "Händelseavisering",
|
||||||
"apprise-url-skipped-if-blank": "Apprise-URL (hoppa över om tom)",
|
"apprise-url-skipped-if-blank": "Apprise-URL (hoppa över om tom)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Aktivera avisering",
|
"enable-notifier": "Aktivera avisering",
|
||||||
"what-events": "Vilka händelser ska denna avisering prenumerera på?",
|
"what-events": "Vilka händelser ska denna avisering prenumerera på?",
|
||||||
"user-events": "Användarhändelser",
|
"user-events": "Användarhändelser",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Yeni bildirim",
|
"new-notification": "Yeni bildirim",
|
||||||
"event-notifiers": "Etkinlik Bildirimleri",
|
"event-notifiers": "Etkinlik Bildirimleri",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL'si (boşsa geçilir)",
|
"apprise-url-skipped-if-blank": "Apprise URL'si (boşsa geçilir)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Bildiriciyi Etkinleştir",
|
"enable-notifier": "Bildiriciyi Etkinleştir",
|
||||||
"what-events": "Bu bildirimci hangi olaylara abone olmalıdır?",
|
"what-events": "Bu bildirimci hangi olaylara abone olmalıdır?",
|
||||||
"user-events": "Kullanıcı Etkinlikleri",
|
"user-events": "Kullanıcı Etkinlikleri",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Нове сповіщення",
|
"new-notification": "Нове сповіщення",
|
||||||
"event-notifiers": "Сповіщувачі",
|
"event-notifiers": "Сповіщувачі",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (пропущено якщо порожній)",
|
"apprise-url-skipped-if-blank": "Apprise URL (пропущено якщо порожній)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Увімкнути сповіщувач",
|
"enable-notifier": "Увімкнути сповіщувач",
|
||||||
"what-events": "На які події цей сповіщувач має бути підписаний?",
|
"what-events": "На які події цей сповіщувач має бути підписаний?",
|
||||||
"user-events": "Події користувача",
|
"user-events": "Події користувача",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "Thông báo mới",
|
"new-notification": "Thông báo mới",
|
||||||
"event-notifiers": "Event Notifiers",
|
"event-notifiers": "Event Notifiers",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (skipped if blank)",
|
"apprise-url-skipped-if-blank": "Apprise URL (skipped if blank)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "Enable Notifier",
|
"enable-notifier": "Enable Notifier",
|
||||||
"what-events": "What events should this notifier subscribe to?",
|
"what-events": "What events should this notifier subscribe to?",
|
||||||
"user-events": "User Events",
|
"user-events": "User Events",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "新通知",
|
"new-notification": "新通知",
|
||||||
"event-notifiers": "事件通知器",
|
"event-notifiers": "事件通知器",
|
||||||
"apprise-url-skipped-if-blank": "Apprise URL (如果为空则跳过)",
|
"apprise-url-skipped-if-blank": "Apprise URL (如果为空则跳过)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "打开消息通知",
|
"enable-notifier": "打开消息通知",
|
||||||
"what-events": "该通知器需要订阅哪些事件?",
|
"what-events": "该通知器需要订阅哪些事件?",
|
||||||
"user-events": "用户事件",
|
"user-events": "用户事件",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"new-notification": "新通知",
|
"new-notification": "新通知",
|
||||||
"event-notifiers": "事件通知",
|
"event-notifiers": "事件通知",
|
||||||
"apprise-url-skipped-if-blank": "Apprise 網址(空白則略過)",
|
"apprise-url-skipped-if-blank": "Apprise 網址(空白則略過)",
|
||||||
|
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||||
"enable-notifier": "啟用通知功能",
|
"enable-notifier": "啟用通知功能",
|
||||||
"what-events": "要訂閱哪些事件通知?",
|
"what-events": "要訂閱哪些事件通知?",
|
||||||
"user-events": "用戶相關事件",
|
"user-events": "用戶相關事件",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
|
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
|
||||||
import { RecipeCookBook } from "~/lib/api/types/cookbook";
|
import { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||||
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
|
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
|
||||||
|
|
||||||
const prefix = "/api";
|
const prefix = "/api";
|
||||||
|
@ -10,7 +10,7 @@ const routes = {
|
||||||
cookbooksGroupSlugCookbookId: (groupSlug: string | number, cookbookId: string | number) => `${exploreGroupSlug(groupSlug)}/cookbooks/${cookbookId}`,
|
cookbooksGroupSlugCookbookId: (groupSlug: string | number, cookbookId: string | number) => `${exploreGroupSlug(groupSlug)}/cookbooks/${cookbookId}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class PublicCookbooksApi extends BaseCRUDAPIReadOnly<RecipeCookBook> {
|
export class PublicCookbooksApi extends BaseCRUDAPIReadOnly<ReadCookBook> {
|
||||||
constructor(requests: ApiRequestInstance, groupSlug: string) {
|
constructor(requests: ApiRequestInstance, groupSlug: string) {
|
||||||
super(
|
super(
|
||||||
requests,
|
requests,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
@ -38,67 +39,6 @@ export interface QueryFilterJSONPart {
|
||||||
attributeName?: string | null;
|
attributeName?: string | null;
|
||||||
relationalOperator?: RelationalKeyword | RelationalOperator | null;
|
relationalOperator?: RelationalKeyword | RelationalOperator | null;
|
||||||
value?: string | string[] | null;
|
value?: string | string[] | null;
|
||||||
}
|
|
||||||
export interface RecipeCookBook {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
slug?: string | null;
|
|
||||||
position?: number;
|
|
||||||
public?: boolean;
|
|
||||||
queryFilterString?: string;
|
|
||||||
groupId: string;
|
|
||||||
householdId: string;
|
|
||||||
id: string;
|
|
||||||
queryFilter?: QueryFilterJSON;
|
|
||||||
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;
|
[k: string]: unknown;
|
||||||
}
|
}
|
||||||
export interface SaveCookBook {
|
export interface SaveCookBook {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
/* This file was automatically generated from pydantic models by running pydantic2ts.
|
||||||
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseCRUDAPI } from "../base/base-clients";
|
import { BaseCRUDAPI } from "../base/base-clients";
|
||||||
import type { CreateCookBook, RecipeCookBook, UpdateCookBook } from "~/lib/api/types/cookbook";
|
import type { CreateCookBook, ReadCookBook, UpdateCookBook } from "~/lib/api/types/cookbook";
|
||||||
|
|
||||||
const prefix = "/api";
|
const prefix = "/api";
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const routes = {
|
||||||
cookbooksId: (id: number) => `${prefix}/households/cookbooks/${id}`,
|
cookbooksId: (id: number) => `${prefix}/households/cookbooks/${id}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CookbookAPI extends BaseCRUDAPI<CreateCookBook, RecipeCookBook, UpdateCookBook> {
|
export class CookbookAPI extends BaseCRUDAPI<CreateCookBook, ReadCookBook, UpdateCookBook> {
|
||||||
baseRoute: string = routes.cookbooks;
|
baseRoute: string = routes.cookbooks;
|
||||||
itemRoute = routes.cookbooksId;
|
itemRoute = routes.cookbooksId;
|
||||||
|
|
||||||
|
|
2
frontend/types/components.d.ts
vendored
2
frontend/types/components.d.ts
vendored
|
@ -81,4 +81,4 @@ declare module "vue" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { };
|
export {};
|
||||||
|
|
|
@ -100,12 +100,12 @@
|
||||||
"sweet corn": {
|
"sweet corn": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "sweet corn",
|
"name": "mais dolce",
|
||||||
"plural_name": "sweet corns"
|
"plural_name": "mais dolci"
|
||||||
},
|
},
|
||||||
"chile pepper": {
|
"chile pepper": {
|
||||||
"aliases": [
|
"aliases": [
|
||||||
"capsicum"
|
"peperoncino"
|
||||||
],
|
],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "peperoncino",
|
"name": "peperoncino",
|
||||||
|
@ -132,8 +132,8 @@
|
||||||
"baby green": {
|
"baby green": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "baby green",
|
"name": "insalatina",
|
||||||
"plural_name": "baby greens"
|
"plural_name": "insalatine"
|
||||||
},
|
},
|
||||||
"pumpkin": {
|
"pumpkin": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -151,112 +151,112 @@
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "cavolo",
|
"name": "cavolo",
|
||||||
"plural_name": "cabbages"
|
"plural_name": "cavoli"
|
||||||
},
|
},
|
||||||
"asparagu": {
|
"asparagu": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "asparagu",
|
"name": "asparago",
|
||||||
"plural_name": "asparagus"
|
"plural_name": "asparagi"
|
||||||
},
|
},
|
||||||
"kale": {
|
"kale": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "kale",
|
"name": "cavolo riccio",
|
||||||
"plural_name": "kales"
|
"plural_name": "cavoli ricci"
|
||||||
},
|
},
|
||||||
"arugula": {
|
"arugula": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "arugula",
|
"name": "rucola",
|
||||||
"plural_name": "arugulas"
|
"plural_name": "rucole"
|
||||||
},
|
},
|
||||||
"leek": {
|
"leek": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "leek",
|
"name": "porro",
|
||||||
"plural_name": "leeks"
|
"plural_name": "porri"
|
||||||
},
|
},
|
||||||
"eggplant": {
|
"eggplant": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "eggplant",
|
"name": "melanzana",
|
||||||
"plural_name": "eggplants"
|
"plural_name": "melanzane"
|
||||||
},
|
},
|
||||||
"lettuce": {
|
"lettuce": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "lettuce",
|
"name": "lattuga",
|
||||||
"plural_name": "lettuces"
|
"plural_name": "lattughe"
|
||||||
},
|
},
|
||||||
"butternut squash": {
|
"butternut squash": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "butternut squash",
|
"name": "zucca violina",
|
||||||
"plural_name": "butternut squashes"
|
"plural_name": "zucche violine"
|
||||||
},
|
},
|
||||||
"romaine": {
|
"romaine": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "romaine",
|
"name": "lattuga romana",
|
||||||
"plural_name": "romaines"
|
"plural_name": "lattughe romane"
|
||||||
},
|
},
|
||||||
"beetroot": {
|
"beetroot": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "beetroot",
|
"name": "barbabietola",
|
||||||
"plural_name": "beetroots"
|
"plural_name": "barbabietole"
|
||||||
},
|
},
|
||||||
"brussels sprout": {
|
"brussels sprout": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "brussels sprout",
|
"name": "cavoletto di Bruxelles",
|
||||||
"plural_name": "brussels sprouts"
|
"plural_name": "cavoletti di Bruxelles"
|
||||||
},
|
},
|
||||||
"fennel": {
|
"fennel": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "fennel",
|
"name": "finocchio",
|
||||||
"plural_name": "fennels"
|
"plural_name": "finocchi"
|
||||||
},
|
},
|
||||||
"sun dried tomato": {
|
"sun dried tomato": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "sun dried tomato",
|
"name": "pomodoro essiccato al sole",
|
||||||
"plural_name": "sun dried tomatoes"
|
"plural_name": "pomodori essiccati al sole"
|
||||||
},
|
},
|
||||||
"radish": {
|
"radish": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "radish",
|
"name": "ravanello",
|
||||||
"plural_name": "radishes"
|
"plural_name": "ravanelli"
|
||||||
},
|
},
|
||||||
"red cabbage": {
|
"red cabbage": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "red cabbage",
|
"name": "cavolo rosso",
|
||||||
"plural_name": "red cabbages"
|
"plural_name": "cavoli rossi"
|
||||||
},
|
},
|
||||||
"artichoke": {
|
"artichoke": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "artichoke",
|
"name": "carciofo",
|
||||||
"plural_name": "artichokes"
|
"plural_name": "carciofi"
|
||||||
},
|
},
|
||||||
"new potato": {
|
"new potato": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "new potato",
|
"name": "patata nuova",
|
||||||
"plural_name": "new potatoes"
|
"plural_name": "patate nuove"
|
||||||
},
|
},
|
||||||
"summer squash": {
|
"summer squash": {
|
||||||
"aliases": [
|
"aliases": [
|
||||||
"courgette",
|
"zucchina",
|
||||||
"gem squash"
|
"gem squash"
|
||||||
],
|
],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "summer squash",
|
"name": "zucca estiva",
|
||||||
"plural_name": "summer squashes"
|
"plural_name": "zucche estive"
|
||||||
},
|
},
|
||||||
"mixed green": {
|
"mixed green": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -267,20 +267,20 @@
|
||||||
"parsnip": {
|
"parsnip": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "parsnip",
|
"name": "pastinaca",
|
||||||
"plural_name": "parsnips"
|
"plural_name": "pastinache"
|
||||||
},
|
},
|
||||||
"baby carrot": {
|
"baby carrot": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "baby carrot",
|
"name": "carotina",
|
||||||
"plural_name": "baby carrots"
|
"plural_name": "carotine"
|
||||||
},
|
},
|
||||||
"mixed vegetable": {
|
"mixed vegetable": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "mixed vegetable",
|
"name": "ortaggi misti",
|
||||||
"plural_name": "mixed vegetables"
|
"plural_name": "ortaggi misti"
|
||||||
},
|
},
|
||||||
"poblano pepper": {
|
"poblano pepper": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -303,50 +303,50 @@
|
||||||
"cayenne pepper": {
|
"cayenne pepper": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "cayenne pepper",
|
"name": "pepe di Caienna",
|
||||||
"plural_name": "cayenne peppers"
|
"plural_name": "pepi di Caienna"
|
||||||
},
|
},
|
||||||
"green tomato": {
|
"green tomato": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "green tomato",
|
"name": "pomodoro verde",
|
||||||
"plural_name": "green tomatoes"
|
"plural_name": "pomodori verdi"
|
||||||
},
|
},
|
||||||
"watercress": {
|
"watercress": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "watercress",
|
"name": "crescione",
|
||||||
"plural_name": "watercress"
|
"plural_name": "crescioni"
|
||||||
},
|
},
|
||||||
"iceberg": {
|
"iceberg": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "iceberg",
|
"name": "iceberg",
|
||||||
"plural_name": "icebergs"
|
"plural_name": "iceberg"
|
||||||
},
|
},
|
||||||
"mashed potato": {
|
"mashed potato": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "mashed potato",
|
"name": "purè di patate",
|
||||||
"plural_name": "mashed potatoes"
|
"plural_name": "purè di patate"
|
||||||
},
|
},
|
||||||
"horseradish": {
|
"horseradish": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "horseradish",
|
"name": "rafano",
|
||||||
"plural_name": "horseradishes"
|
"plural_name": "rafani"
|
||||||
},
|
},
|
||||||
"chard": {
|
"chard": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "chard",
|
"name": "bietola",
|
||||||
"plural_name": "chards"
|
"plural_name": "bietole"
|
||||||
},
|
},
|
||||||
"pimiento": {
|
"pimiento": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "pimiento",
|
"name": "pimiento",
|
||||||
"plural_name": "pimientoes"
|
"plural_name": "pimienti"
|
||||||
},
|
},
|
||||||
"spaghetti squash": {
|
"spaghetti squash": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -389,8 +389,8 @@
|
||||||
"turnip": {
|
"turnip": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "turnip",
|
"name": "rapa",
|
||||||
"plural_name": "turnips"
|
"plural_name": "rape"
|
||||||
},
|
},
|
||||||
"thai chile pepper": {
|
"thai chile pepper": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -443,8 +443,8 @@
|
||||||
"plantain": {
|
"plantain": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "plantain",
|
"name": "platano",
|
||||||
"plural_name": "plantains"
|
"plural_name": "platani"
|
||||||
},
|
},
|
||||||
"leaf lettuce": {
|
"leaf lettuce": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|
|
@ -310,7 +310,7 @@
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "green tomato",
|
"name": "green tomato",
|
||||||
"plural_name": "green tomatoes"
|
"plural_name": "zielone pomidory"
|
||||||
},
|
},
|
||||||
"watercress": {
|
"watercress": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -357,8 +357,8 @@
|
||||||
"butter lettuce": {
|
"butter lettuce": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "butter lettuce",
|
"name": "sałata masłowa",
|
||||||
"plural_name": "butter lettuces"
|
"plural_name": "sałaty masłowe"
|
||||||
},
|
},
|
||||||
"hash brown": {
|
"hash brown": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -389,8 +389,8 @@
|
||||||
"turnip": {
|
"turnip": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "turnip",
|
"name": "rzepa",
|
||||||
"plural_name": "turnips"
|
"plural_name": "rzepy"
|
||||||
},
|
},
|
||||||
"thai chile pepper": {
|
"thai chile pepper": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -851,8 +851,8 @@
|
||||||
"dried fruit": {
|
"dried fruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried fruit",
|
"name": "Suszony owoc",
|
||||||
"plural_name": "dried fruits"
|
"plural_name": "Suszone owoce"
|
||||||
},
|
},
|
||||||
"clementine": {
|
"clementine": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -881,14 +881,14 @@
|
||||||
"dried mango": {
|
"dried mango": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried mango",
|
"name": "Suszone mango",
|
||||||
"plural_name": "dried mangoes"
|
"plural_name": "Suszone mango"
|
||||||
},
|
},
|
||||||
"dried apple": {
|
"dried apple": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried apple",
|
"name": "Suszone jabłko",
|
||||||
"plural_name": "dried apples"
|
"plural_name": "Suszone jabłka"
|
||||||
},
|
},
|
||||||
"quince": {
|
"quince": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -912,7 +912,7 @@
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "kumquat",
|
"name": "kumquat",
|
||||||
"plural_name": "kumquats"
|
"plural_name": "kumkwat"
|
||||||
},
|
},
|
||||||
"jackfruit": {
|
"jackfruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -923,8 +923,8 @@
|
||||||
"dragon fruit": {
|
"dragon fruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dragon fruit",
|
"name": "smoczy owoc",
|
||||||
"plural_name": "dragon fruits"
|
"plural_name": "smocze owoce"
|
||||||
},
|
},
|
||||||
"mixed fruit": {
|
"mixed fruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -959,20 +959,20 @@
|
||||||
"star fruit": {
|
"star fruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "star fruit",
|
"name": "karambola",
|
||||||
"plural_name": "star fruits"
|
"plural_name": "karambole"
|
||||||
},
|
},
|
||||||
"green papaya": {
|
"green papaya": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "green papaya",
|
"name": "zielona papaja",
|
||||||
"plural_name": "green papayas"
|
"plural_name": "zielone papaje"
|
||||||
},
|
},
|
||||||
"pomelo": {
|
"pomelo": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "pomelo",
|
"name": "pomelo",
|
||||||
"plural_name": "pomeloes"
|
"plural_name": "pomelo"
|
||||||
},
|
},
|
||||||
"chestnut puree": {
|
"chestnut puree": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1055,8 +1055,8 @@
|
||||||
"dried lemon": {
|
"dried lemon": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried lemon",
|
"name": "Suszona cytryna",
|
||||||
"plural_name": "dried lemons"
|
"plural_name": "Suszone cytryny"
|
||||||
},
|
},
|
||||||
"young jackfruit": {
|
"young jackfruit": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1068,7 +1068,7 @@
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "durian",
|
"name": "durian",
|
||||||
"plural_name": "durians"
|
"plural_name": "duriany"
|
||||||
},
|
},
|
||||||
"freeze-dried apple": {
|
"freeze-dried apple": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1245,8 +1245,8 @@
|
||||||
"shiitake mushroom": {
|
"shiitake mushroom": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "shiitake mushroom",
|
"name": "Grzyb Shiitake",
|
||||||
"plural_name": "shiitake mushrooms"
|
"plural_name": "Grzyby Shiitake"
|
||||||
},
|
},
|
||||||
"portobello mushroom": {
|
"portobello mushroom": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1299,8 +1299,8 @@
|
||||||
"black truffle": {
|
"black truffle": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "black truffle",
|
"name": "czarna trufla",
|
||||||
"plural_name": "black truffles"
|
"plural_name": "czarne trufle"
|
||||||
},
|
},
|
||||||
"morel mushroom": {
|
"morel mushroom": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1353,8 +1353,8 @@
|
||||||
"white truffle": {
|
"white truffle": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "white truffle",
|
"name": "biała trufla",
|
||||||
"plural_name": "white truffles"
|
"plural_name": "białe trufle"
|
||||||
},
|
},
|
||||||
"white fungu": {
|
"white fungu": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1453,26 +1453,26 @@
|
||||||
"strawberry": {
|
"strawberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "strawberry",
|
"name": "truskawka",
|
||||||
"plural_name": "strawberries"
|
"plural_name": "truskawki"
|
||||||
},
|
},
|
||||||
"blueberry": {
|
"blueberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "blueberry",
|
"name": "borówka",
|
||||||
"plural_name": "blueberries"
|
"plural_name": "borówki"
|
||||||
},
|
},
|
||||||
"raspberry": {
|
"raspberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "raspberry",
|
"name": "malina",
|
||||||
"plural_name": "raspberries"
|
"plural_name": "maliny"
|
||||||
},
|
},
|
||||||
"cranberry": {
|
"cranberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "cranberry",
|
"name": "żurawina",
|
||||||
"plural_name": "cranberries"
|
"plural_name": "żurawiny"
|
||||||
},
|
},
|
||||||
"cherry": {
|
"cherry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1483,8 +1483,8 @@
|
||||||
"blackberry": {
|
"blackberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "blackberry",
|
"name": "jeżyna",
|
||||||
"plural_name": "blackberries"
|
"plural_name": "jeżyny"
|
||||||
},
|
},
|
||||||
"berry mix": {
|
"berry mix": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1519,14 +1519,14 @@
|
||||||
"goji berry": {
|
"goji berry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "goji berry",
|
"name": "jagoda goji",
|
||||||
"plural_name": "goji berries"
|
"plural_name": "jagody goji"
|
||||||
},
|
},
|
||||||
"dried blueberry": {
|
"dried blueberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried blueberry",
|
"name": "Suszona borówka",
|
||||||
"plural_name": "dried blueberries"
|
"plural_name": "Suszone borówki"
|
||||||
},
|
},
|
||||||
"freeze-dried strawberry": {
|
"freeze-dried strawberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1537,8 +1537,8 @@
|
||||||
"gooseberry": {
|
"gooseberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "gooseberry",
|
"name": "agrest",
|
||||||
"plural_name": "gooseberries"
|
"plural_name": "agresty"
|
||||||
},
|
},
|
||||||
"freeze-dried raspberry": {
|
"freeze-dried raspberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1561,14 +1561,14 @@
|
||||||
"mulberry": {
|
"mulberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "mulberry",
|
"name": "morwa",
|
||||||
"plural_name": "mulberries"
|
"plural_name": "morwy"
|
||||||
},
|
},
|
||||||
"acai berry": {
|
"acai berry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "acai berry",
|
"name": "jagoda acai",
|
||||||
"plural_name": "acai berries"
|
"plural_name": "jagody acai"
|
||||||
},
|
},
|
||||||
"canned cherry": {
|
"canned cherry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1585,8 +1585,8 @@
|
||||||
"elderberry": {
|
"elderberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "elderberry",
|
"name": "czarny bez",
|
||||||
"plural_name": "elderberries"
|
"plural_name": "czarny bez"
|
||||||
},
|
},
|
||||||
"freeze-dried blueberry": {
|
"freeze-dried blueberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -1663,8 +1663,8 @@
|
||||||
"aronia berry": {
|
"aronia berry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "aronia berry",
|
"name": "jagoda aronii",
|
||||||
"plural_name": "aronia berries"
|
"plural_name": "jagody aronii"
|
||||||
},
|
},
|
||||||
"chokeberry": {
|
"chokeberry": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -5181,8 +5181,8 @@
|
||||||
"dried anchovy": {
|
"dried anchovy": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried anchovy",
|
"name": "Suszona anszua",
|
||||||
"plural_name": "dried anchovies"
|
"plural_name": "Suszone anszua"
|
||||||
},
|
},
|
||||||
"arctic char": {
|
"arctic char": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -5331,8 +5331,8 @@
|
||||||
"dried fish": {
|
"dried fish": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried fish",
|
"name": "suszona ryba",
|
||||||
"plural_name": "dried fish"
|
"plural_name": "suszone ryby"
|
||||||
},
|
},
|
||||||
"flathead": {
|
"flathead": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -5587,8 +5587,8 @@
|
||||||
"dried shrimp": {
|
"dried shrimp": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried shrimp",
|
"name": "suszona garnela",
|
||||||
"plural_name": "dried shrimps"
|
"plural_name": "suszone garnele"
|
||||||
},
|
},
|
||||||
"bay scallop": {
|
"bay scallop": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -5641,8 +5641,8 @@
|
||||||
"dried prawn": {
|
"dried prawn": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried prawn",
|
"name": "suszona krewetka",
|
||||||
"plural_name": "dried prawns"
|
"plural_name": "suszone krewetki"
|
||||||
},
|
},
|
||||||
"dulse seaweed": {
|
"dulse seaweed": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -6215,8 +6215,8 @@
|
||||||
"dried chili": {
|
"dried chili": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried chili",
|
"name": "suszone chili",
|
||||||
"plural_name": "dried chilies"
|
"plural_name": "suszone chili"
|
||||||
},
|
},
|
||||||
"black cardamom": {
|
"black cardamom": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
@ -9332,8 +9332,8 @@
|
||||||
"dried pea": {
|
"dried pea": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"name": "dried pea",
|
"name": "suszony groch",
|
||||||
"plural_name": "dried peas"
|
"plural_name": "suszony groch"
|
||||||
},
|
},
|
||||||
"pink bean": {
|
"pink bean": {
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|
|
@ -19,6 +19,8 @@ from mealie.routes._base.routers import UserAPIRouter
|
||||||
from mealie.schema.user import PrivateUser
|
from mealie.schema.user import PrivateUser
|
||||||
from mealie.schema.user.auth import CredentialsRequestForm
|
from mealie.schema.user.auth import CredentialsRequestForm
|
||||||
|
|
||||||
|
from .auth_cache import AuthCache
|
||||||
|
|
||||||
public_router = APIRouter(tags=["Users: Authentication"])
|
public_router = APIRouter(tags=["Users: Authentication"])
|
||||||
user_router = UserAPIRouter(tags=["Users: Authentication"])
|
user_router = UserAPIRouter(tags=["Users: Authentication"])
|
||||||
logger = root_logger.get_logger("auth")
|
logger = root_logger.get_logger("auth")
|
||||||
|
@ -27,7 +29,7 @@ remember_me_duration = timedelta(days=14)
|
||||||
|
|
||||||
settings = get_app_settings()
|
settings = get_app_settings()
|
||||||
if settings.OIDC_READY:
|
if settings.OIDC_READY:
|
||||||
oauth = OAuth()
|
oauth = OAuth(cache=AuthCache())
|
||||||
scope = None
|
scope = None
|
||||||
if settings.OIDC_SCOPES_OVERRIDE:
|
if settings.OIDC_SCOPES_OVERRIDE:
|
||||||
scope = settings.OIDC_SCOPES_OVERRIDE
|
scope = settings.OIDC_SCOPES_OVERRIDE
|
||||||
|
|
51
mealie/routes/auth/auth_cache.py
Normal file
51
mealie/routes/auth/auth_cache.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import time
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class AuthCache:
|
||||||
|
def __init__(self, threshold: int = 500, default_timeout: float = 300):
|
||||||
|
self.default_timeout = default_timeout
|
||||||
|
self._cache: dict[str, tuple[float, Any]] = {}
|
||||||
|
self.clear = self._cache.clear
|
||||||
|
self._threshold = threshold
|
||||||
|
|
||||||
|
def _prune(self):
|
||||||
|
if len(self._cache) > self._threshold:
|
||||||
|
now = time.time()
|
||||||
|
toremove = []
|
||||||
|
for idx, (key, (expires, _)) in enumerate(self._cache.items()):
|
||||||
|
if (expires != 0 and expires <= now) or idx % 3 == 0:
|
||||||
|
toremove.append(key)
|
||||||
|
for key in toremove:
|
||||||
|
self._cache.pop(key, None)
|
||||||
|
|
||||||
|
def _normalize_timeout(self, timeout: float | None) -> float:
|
||||||
|
if timeout is None:
|
||||||
|
timeout = self.default_timeout
|
||||||
|
if timeout > 0:
|
||||||
|
timeout = time.time() + timeout
|
||||||
|
return timeout
|
||||||
|
|
||||||
|
async def get(self, key: str) -> Any:
|
||||||
|
try:
|
||||||
|
expires, value = self._cache[key]
|
||||||
|
if expires == 0 or expires > time.time():
|
||||||
|
return value
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def set(self, key: str, value: Any, timeout: float | None = None) -> bool:
|
||||||
|
expires = self._normalize_timeout(timeout)
|
||||||
|
self._prune()
|
||||||
|
self._cache[key] = (expires, value)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def delete(self, key: str) -> bool:
|
||||||
|
return self._cache.pop(key, None) is not None
|
||||||
|
|
||||||
|
async def has(self, key: str) -> bool:
|
||||||
|
try:
|
||||||
|
expires, value = self._cache[key]
|
||||||
|
return expires == 0 or expires > time.time()
|
||||||
|
except KeyError:
|
||||||
|
return False
|
|
@ -5,7 +5,7 @@ from pydantic import UUID4
|
||||||
|
|
||||||
from mealie.routes._base import controller
|
from mealie.routes._base import controller
|
||||||
from mealie.routes._base.base_controllers import BasePublicHouseholdExploreController
|
from mealie.routes._base.base_controllers import BasePublicHouseholdExploreController
|
||||||
from mealie.schema.cookbook.cookbook import ReadCookBook, RecipeCookBook
|
from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||||
from mealie.schema.make_dependable import make_dependable
|
from mealie.schema.make_dependable import make_dependable
|
||||||
from mealie.schema.response.pagination import PaginationBase, PaginationQuery
|
from mealie.schema.response.pagination import PaginationBase, PaginationQuery
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ class PublicCookbooksController(BasePublicHouseholdExploreController):
|
||||||
response.set_pagination_guides(self.get_explore_url_path(router.url_path_for("get_all")), q.model_dump())
|
response.set_pagination_guides(self.get_explore_url_path(router.url_path_for("get_all")), q.model_dump())
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@router.get("/{item_id}", response_model=RecipeCookBook)
|
@router.get("/{item_id}", response_model=ReadCookBook)
|
||||||
def get_one(self, item_id: UUID4 | str) -> RecipeCookBook:
|
def get_one(self, item_id: UUID4 | str) -> ReadCookBook:
|
||||||
NOT_FOUND_EXCEPTION = HTTPException(404, "cookbook not found")
|
NOT_FOUND_EXCEPTION = HTTPException(404, "cookbook not found")
|
||||||
if isinstance(item_id, UUID):
|
if isinstance(item_id, UUID):
|
||||||
match_attr = "id"
|
match_attr = "id"
|
||||||
|
@ -58,13 +58,4 @@ class PublicCookbooksController(BasePublicHouseholdExploreController):
|
||||||
if not household or household.preferences.private_household:
|
if not household or household.preferences.private_household:
|
||||||
raise NOT_FOUND_EXCEPTION
|
raise NOT_FOUND_EXCEPTION
|
||||||
|
|
||||||
cross_household_recipes = self.cross_household_repos.recipes
|
return cookbook
|
||||||
recipes = cross_household_recipes.page_all(
|
|
||||||
PaginationQuery(
|
|
||||||
page=1,
|
|
||||||
per_page=-1,
|
|
||||||
query_filter="settings.public = TRUE AND household.preferences.privateHousehold = FALSE",
|
|
||||||
),
|
|
||||||
cookbook=cookbook,
|
|
||||||
)
|
|
||||||
return cookbook.cast(RecipeCookBook, recipes=recipes.items)
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ from mealie.routes._base import BaseCrudController, controller
|
||||||
from mealie.routes._base.mixins import HttpRepo
|
from mealie.routes._base.mixins import HttpRepo
|
||||||
from mealie.routes._base.routers import MealieCrudRoute
|
from mealie.routes._base.routers import MealieCrudRoute
|
||||||
from mealie.schema import mapper
|
from mealie.schema import mapper
|
||||||
from mealie.schema.cookbook import CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
|
from mealie.schema.cookbook import CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook
|
||||||
from mealie.schema.cookbook.cookbook import CookBookPagination
|
from mealie.schema.cookbook.cookbook import CookBookPagination
|
||||||
from mealie.schema.response.pagination import PaginationQuery
|
from mealie.schema.response.pagination import PaginationQuery
|
||||||
from mealie.services.event_bus_service.event_types import (
|
from mealie.services.event_bus_service.event_types import (
|
||||||
|
@ -101,7 +101,7 @@ class GroupCookbookController(BaseCrudController):
|
||||||
|
|
||||||
return all_updated
|
return all_updated
|
||||||
|
|
||||||
@router.get("/{item_id}", response_model=RecipeCookBook)
|
@router.get("/{item_id}", response_model=ReadCookBook)
|
||||||
def get_one(self, item_id: UUID4 | str):
|
def get_one(self, item_id: UUID4 | str):
|
||||||
if isinstance(item_id, UUID):
|
if isinstance(item_id, UUID):
|
||||||
match_attr = "id"
|
match_attr = "id"
|
||||||
|
@ -114,12 +114,10 @@ class GroupCookbookController(BaseCrudController):
|
||||||
|
|
||||||
# Allow fetching other households' cookbooks
|
# Allow fetching other households' cookbooks
|
||||||
cookbook = self.group_cookbooks.get_one(item_id, match_attr)
|
cookbook = self.group_cookbooks.get_one(item_id, match_attr)
|
||||||
|
|
||||||
if cookbook is None:
|
if cookbook is None:
|
||||||
raise HTTPException(status_code=404)
|
raise HTTPException(status_code=404)
|
||||||
|
|
||||||
recipe_pagination = self.repos.recipes.page_all(PaginationQuery(page=1, per_page=-1, cookbook=cookbook))
|
return cookbook
|
||||||
return cookbook.cast(RecipeCookBook, recipes=recipe_pagination.items)
|
|
||||||
|
|
||||||
@router.put("/{item_id}", response_model=ReadCookBook)
|
@router.put("/{item_id}", response_model=ReadCookBook)
|
||||||
def update_one(self, item_id: str, data: CreateCookBook):
|
def update_one(self, item_id: str, data: CreateCookBook):
|
||||||
|
|
|
@ -3,11 +3,11 @@ from .datetime_parse import DateError, DateTimeError, DurationError, TimeError
|
||||||
from .mealie_model import HasUUID, MealieModel, SearchType
|
from .mealie_model import HasUUID, MealieModel, SearchType
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"HasUUID",
|
|
||||||
"MealieModel",
|
|
||||||
"SearchType",
|
|
||||||
"DateError",
|
"DateError",
|
||||||
"DateTimeError",
|
"DateTimeError",
|
||||||
"DurationError",
|
"DurationError",
|
||||||
"TimeError",
|
"TimeError",
|
||||||
|
"HasUUID",
|
||||||
|
"MealieModel",
|
||||||
|
"SearchType",
|
||||||
]
|
]
|
||||||
|
|
|
@ -18,10 +18,28 @@ from .restore import (
|
||||||
from .settings import CustomPageBase, CustomPageOut
|
from .settings import CustomPageBase, CustomPageOut
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"MaintenanceLogs",
|
||||||
|
"MaintenanceStorageDetails",
|
||||||
|
"MaintenanceSummary",
|
||||||
"ChowdownURL",
|
"ChowdownURL",
|
||||||
"MigrationFile",
|
"MigrationFile",
|
||||||
"MigrationImport",
|
"MigrationImport",
|
||||||
"Migrations",
|
"Migrations",
|
||||||
|
"CustomPageBase",
|
||||||
|
"CustomPageOut",
|
||||||
|
"CommentImport",
|
||||||
|
"CustomPageImport",
|
||||||
|
"GroupImport",
|
||||||
|
"ImportBase",
|
||||||
|
"NotificationImport",
|
||||||
|
"RecipeImport",
|
||||||
|
"SettingsImport",
|
||||||
|
"UserImport",
|
||||||
|
"AllBackups",
|
||||||
|
"BackupFile",
|
||||||
|
"BackupOptions",
|
||||||
|
"CreateBackup",
|
||||||
|
"ImportJob",
|
||||||
"AdminAboutInfo",
|
"AdminAboutInfo",
|
||||||
"AppInfo",
|
"AppInfo",
|
||||||
"AppStartupInfo",
|
"AppStartupInfo",
|
||||||
|
@ -31,23 +49,5 @@ __all__ = [
|
||||||
"EmailReady",
|
"EmailReady",
|
||||||
"EmailSuccess",
|
"EmailSuccess",
|
||||||
"EmailTest",
|
"EmailTest",
|
||||||
"CustomPageBase",
|
|
||||||
"CustomPageOut",
|
|
||||||
"AllBackups",
|
|
||||||
"BackupFile",
|
|
||||||
"BackupOptions",
|
|
||||||
"CreateBackup",
|
|
||||||
"ImportJob",
|
|
||||||
"MaintenanceLogs",
|
|
||||||
"MaintenanceStorageDetails",
|
|
||||||
"MaintenanceSummary",
|
|
||||||
"DebugResponse",
|
"DebugResponse",
|
||||||
"CommentImport",
|
|
||||||
"CustomPageImport",
|
|
||||||
"GroupImport",
|
|
||||||
"ImportBase",
|
|
||||||
"NotificationImport",
|
|
||||||
"RecipeImport",
|
|
||||||
"SettingsImport",
|
|
||||||
"UserImport",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# This file is auto-generated by gen_schema_exports.py
|
# This file is auto-generated by gen_schema_exports.py
|
||||||
from .cookbook import CookBookPagination, CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
|
from .cookbook import CookBookPagination, CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"CookBookPagination",
|
"CookBookPagination",
|
||||||
"CreateCookBook",
|
"CreateCookBook",
|
||||||
"ReadCookBook",
|
"ReadCookBook",
|
||||||
"RecipeCookBook",
|
|
||||||
"SaveCookBook",
|
"SaveCookBook",
|
||||||
"UpdateCookBook",
|
"UpdateCookBook",
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,7 +7,6 @@ from slugify import slugify
|
||||||
from mealie.core.root_logger import get_logger
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.models.recipe import RecipeModel
|
from mealie.db.models.recipe import RecipeModel
|
||||||
from mealie.schema._mealie import MealieModel
|
from mealie.schema._mealie import MealieModel
|
||||||
from mealie.schema.recipe.recipe import RecipeSummary
|
|
||||||
from mealie.schema.response.pagination import PaginationBase
|
from mealie.schema.response.pagination import PaginationBase
|
||||||
from mealie.schema.response.query_filter import QueryFilterBuilder, QueryFilterJSON
|
from mealie.schema.response.query_filter import QueryFilterBuilder, QueryFilterJSON
|
||||||
|
|
||||||
|
@ -84,10 +83,3 @@ class ReadCookBook(UpdateCookBook):
|
||||||
|
|
||||||
class CookBookPagination(PaginationBase):
|
class CookBookPagination(PaginationBase):
|
||||||
items: list[ReadCookBook]
|
items: list[ReadCookBook]
|
||||||
|
|
||||||
|
|
||||||
class RecipeCookBook(ReadCookBook):
|
|
||||||
group_id: UUID4
|
|
||||||
household_id: UUID4
|
|
||||||
recipes: list[RecipeSummary]
|
|
||||||
model_config = ConfigDict(from_attributes=True)
|
|
||||||
|
|
|
@ -7,13 +7,13 @@ from .group_seeder import SeederConfig
|
||||||
from .group_statistics import GroupStorage
|
from .group_statistics import GroupStorage
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"GroupAdminUpdate",
|
|
||||||
"GroupStorage",
|
|
||||||
"GroupDataExport",
|
"GroupDataExport",
|
||||||
"SeederConfig",
|
|
||||||
"CreateGroupPreferences",
|
"CreateGroupPreferences",
|
||||||
"ReadGroupPreferences",
|
"ReadGroupPreferences",
|
||||||
"UpdateGroupPreferences",
|
"UpdateGroupPreferences",
|
||||||
|
"GroupStorage",
|
||||||
"DataMigrationCreate",
|
"DataMigrationCreate",
|
||||||
"SupportedMigrations",
|
"SupportedMigrations",
|
||||||
|
"SeederConfig",
|
||||||
|
"GroupAdminUpdate",
|
||||||
]
|
]
|
||||||
|
|
|
@ -70,6 +70,49 @@ from .invite_token import CreateInviteToken, EmailInitationResponse, EmailInvita
|
||||||
from .webhook import CreateWebhook, ReadWebhook, SaveWebhook, WebhookPagination, WebhookType
|
from .webhook import CreateWebhook, ReadWebhook, SaveWebhook, WebhookPagination, WebhookType
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"GroupEventNotifierCreate",
|
||||||
|
"GroupEventNotifierOptions",
|
||||||
|
"GroupEventNotifierOptionsOut",
|
||||||
|
"GroupEventNotifierOptionsSave",
|
||||||
|
"GroupEventNotifierOut",
|
||||||
|
"GroupEventNotifierPrivate",
|
||||||
|
"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",
|
"ShoppingListAddRecipeParams",
|
||||||
"ShoppingListAddRecipeParamsBulk",
|
"ShoppingListAddRecipeParamsBulk",
|
||||||
"ShoppingListCreate",
|
"ShoppingListCreate",
|
||||||
|
@ -93,48 +136,5 @@ __all__ = [
|
||||||
"ShoppingListSave",
|
"ShoppingListSave",
|
||||||
"ShoppingListSummary",
|
"ShoppingListSummary",
|
||||||
"ShoppingListUpdate",
|
"ShoppingListUpdate",
|
||||||
"GroupEventNotifierCreate",
|
|
||||||
"GroupEventNotifierOptions",
|
|
||||||
"GroupEventNotifierOptionsOut",
|
|
||||||
"GroupEventNotifierOptionsSave",
|
|
||||||
"GroupEventNotifierOut",
|
|
||||||
"GroupEventNotifierPrivate",
|
|
||||||
"GroupEventNotifierSave",
|
|
||||||
"GroupEventNotifierUpdate",
|
|
||||||
"GroupEventPagination",
|
|
||||||
"CreateGroupRecipeAction",
|
|
||||||
"GroupRecipeActionOut",
|
|
||||||
"GroupRecipeActionPagination",
|
|
||||||
"GroupRecipeActionPayload",
|
|
||||||
"GroupRecipeActionType",
|
|
||||||
"SaveGroupRecipeAction",
|
|
||||||
"CreateHouseholdPreferences",
|
|
||||||
"ReadHouseholdPreferences",
|
|
||||||
"SaveHouseholdPreferences",
|
|
||||||
"UpdateHouseholdPreferences",
|
|
||||||
"SetPermissions",
|
"SetPermissions",
|
||||||
"CreateInviteToken",
|
|
||||||
"EmailInitationResponse",
|
|
||||||
"EmailInvitation",
|
|
||||||
"ReadInviteToken",
|
|
||||||
"SaveInviteToken",
|
|
||||||
"HouseholdStatistics",
|
|
||||||
"CreateWebhook",
|
|
||||||
"ReadWebhook",
|
|
||||||
"SaveWebhook",
|
|
||||||
"WebhookPagination",
|
|
||||||
"WebhookType",
|
|
||||||
"HouseholdCreate",
|
|
||||||
"HouseholdInDB",
|
|
||||||
"HouseholdPagination",
|
|
||||||
"HouseholdRecipeBase",
|
|
||||||
"HouseholdRecipeCreate",
|
|
||||||
"HouseholdRecipeOut",
|
|
||||||
"HouseholdRecipeSummary",
|
|
||||||
"HouseholdRecipeUpdate",
|
|
||||||
"HouseholdSave",
|
|
||||||
"HouseholdSummary",
|
|
||||||
"HouseholdUserSummary",
|
|
||||||
"UpdateHousehold",
|
|
||||||
"UpdateHouseholdAdmin",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,6 +12,9 @@ from .plan_rules import PlanRulesCreate, PlanRulesDay, PlanRulesOut, PlanRulesPa
|
||||||
from .shopping_list import ListItem, ShoppingListIn, ShoppingListOut
|
from .shopping_list import ListItem, ShoppingListIn, ShoppingListOut
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"ListItem",
|
||||||
|
"ShoppingListIn",
|
||||||
|
"ShoppingListOut",
|
||||||
"CreatePlanEntry",
|
"CreatePlanEntry",
|
||||||
"CreateRandomEntry",
|
"CreateRandomEntry",
|
||||||
"PlanEntryPagination",
|
"PlanEntryPagination",
|
||||||
|
@ -19,9 +22,6 @@ __all__ = [
|
||||||
"ReadPlanEntry",
|
"ReadPlanEntry",
|
||||||
"SavePlanEntry",
|
"SavePlanEntry",
|
||||||
"UpdatePlanEntry",
|
"UpdatePlanEntry",
|
||||||
"ListItem",
|
|
||||||
"ShoppingListIn",
|
|
||||||
"ShoppingListOut",
|
|
||||||
"PlanRulesCreate",
|
"PlanRulesCreate",
|
||||||
"PlanRulesDay",
|
"PlanRulesDay",
|
||||||
"PlanRulesOut",
|
"PlanRulesOut",
|
||||||
|
|
|
@ -89,6 +89,35 @@ from .recipe_tool import RecipeToolCreate, RecipeToolOut, RecipeToolResponse, Re
|
||||||
from .request_helpers import RecipeDuplicate, RecipeSlug, RecipeZipTokenResponse, SlugResponse, UpdateImageResponse
|
from .request_helpers import RecipeDuplicate, RecipeSlug, RecipeZipTokenResponse, SlugResponse, UpdateImageResponse
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"IngredientReferences",
|
||||||
|
"RecipeStep",
|
||||||
|
"RecipeNote",
|
||||||
|
"CategoryBase",
|
||||||
|
"CategoryIn",
|
||||||
|
"CategoryOut",
|
||||||
|
"CategorySave",
|
||||||
|
"RecipeCategoryResponse",
|
||||||
|
"RecipeTagResponse",
|
||||||
|
"TagBase",
|
||||||
|
"TagIn",
|
||||||
|
"TagOut",
|
||||||
|
"TagSave",
|
||||||
|
"RecipeAsset",
|
||||||
|
"RecipeTimelineEventCreate",
|
||||||
|
"RecipeTimelineEventIn",
|
||||||
|
"RecipeTimelineEventOut",
|
||||||
|
"RecipeTimelineEventPagination",
|
||||||
|
"RecipeTimelineEventUpdate",
|
||||||
|
"TimelineEventImage",
|
||||||
|
"TimelineEventType",
|
||||||
|
"RecipeSuggestionQuery",
|
||||||
|
"RecipeSuggestionResponse",
|
||||||
|
"RecipeSuggestionResponseItem",
|
||||||
|
"Nutrition",
|
||||||
|
"RecipeShareToken",
|
||||||
|
"RecipeShareTokenCreate",
|
||||||
|
"RecipeShareTokenSave",
|
||||||
|
"RecipeShareTokenSummary",
|
||||||
"CreateIngredientFood",
|
"CreateIngredientFood",
|
||||||
"CreateIngredientFoodAlias",
|
"CreateIngredientFoodAlias",
|
||||||
"CreateIngredientUnit",
|
"CreateIngredientUnit",
|
||||||
|
@ -111,27 +140,13 @@ __all__ = [
|
||||||
"SaveIngredientFood",
|
"SaveIngredientFood",
|
||||||
"SaveIngredientUnit",
|
"SaveIngredientUnit",
|
||||||
"UnitFoodBase",
|
"UnitFoodBase",
|
||||||
"RecipeTimelineEventCreate",
|
|
||||||
"RecipeTimelineEventIn",
|
|
||||||
"RecipeTimelineEventOut",
|
|
||||||
"RecipeTimelineEventPagination",
|
|
||||||
"RecipeTimelineEventUpdate",
|
|
||||||
"TimelineEventImage",
|
|
||||||
"TimelineEventType",
|
|
||||||
"Nutrition",
|
|
||||||
"AssignCategories",
|
|
||||||
"AssignSettings",
|
|
||||||
"AssignTags",
|
|
||||||
"DeleteRecipes",
|
|
||||||
"ExportBase",
|
|
||||||
"ExportRecipes",
|
|
||||||
"ExportTypes",
|
|
||||||
"RecipeCommentCreate",
|
"RecipeCommentCreate",
|
||||||
"RecipeCommentOut",
|
"RecipeCommentOut",
|
||||||
"RecipeCommentPagination",
|
"RecipeCommentPagination",
|
||||||
"RecipeCommentSave",
|
"RecipeCommentSave",
|
||||||
"RecipeCommentUpdate",
|
"RecipeCommentUpdate",
|
||||||
"UserBase",
|
"UserBase",
|
||||||
|
"RecipeSettings",
|
||||||
"CreateRecipe",
|
"CreateRecipe",
|
||||||
"CreateRecipeBulk",
|
"CreateRecipeBulk",
|
||||||
"CreateRecipeByUrlBulk",
|
"CreateRecipeByUrlBulk",
|
||||||
|
@ -145,40 +160,25 @@ __all__ = [
|
||||||
"RecipeTagPagination",
|
"RecipeTagPagination",
|
||||||
"RecipeTool",
|
"RecipeTool",
|
||||||
"RecipeToolPagination",
|
"RecipeToolPagination",
|
||||||
"IngredientReferences",
|
"ScrapeRecipe",
|
||||||
"RecipeStep",
|
"ScrapeRecipeBase",
|
||||||
"RecipeNote",
|
"ScrapeRecipeData",
|
||||||
"RecipeSuggestionQuery",
|
"ScrapeRecipeTest",
|
||||||
"RecipeSuggestionResponse",
|
"AssignCategories",
|
||||||
"RecipeSuggestionResponseItem",
|
"AssignSettings",
|
||||||
"RecipeSettings",
|
"AssignTags",
|
||||||
"RecipeShareToken",
|
"DeleteRecipes",
|
||||||
"RecipeShareTokenCreate",
|
"ExportBase",
|
||||||
"RecipeShareTokenSave",
|
"ExportRecipes",
|
||||||
"RecipeShareTokenSummary",
|
"ExportTypes",
|
||||||
"RecipeAsset",
|
"RecipeToolCreate",
|
||||||
|
"RecipeToolOut",
|
||||||
|
"RecipeToolResponse",
|
||||||
|
"RecipeToolSave",
|
||||||
|
"RecipeImageTypes",
|
||||||
"RecipeDuplicate",
|
"RecipeDuplicate",
|
||||||
"RecipeSlug",
|
"RecipeSlug",
|
||||||
"RecipeZipTokenResponse",
|
"RecipeZipTokenResponse",
|
||||||
"SlugResponse",
|
"SlugResponse",
|
||||||
"UpdateImageResponse",
|
"UpdateImageResponse",
|
||||||
"RecipeToolCreate",
|
|
||||||
"RecipeToolOut",
|
|
||||||
"RecipeToolResponse",
|
|
||||||
"RecipeToolSave",
|
|
||||||
"CategoryBase",
|
|
||||||
"CategoryIn",
|
|
||||||
"CategoryOut",
|
|
||||||
"CategorySave",
|
|
||||||
"RecipeCategoryResponse",
|
|
||||||
"RecipeTagResponse",
|
|
||||||
"TagBase",
|
|
||||||
"TagIn",
|
|
||||||
"TagOut",
|
|
||||||
"TagSave",
|
|
||||||
"ScrapeRecipe",
|
|
||||||
"ScrapeRecipeBase",
|
|
||||||
"ScrapeRecipeData",
|
|
||||||
"ScrapeRecipeTest",
|
|
||||||
"RecipeImageTypes",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,14 +28,14 @@ __all__ = [
|
||||||
"QueryFilterJSONPart",
|
"QueryFilterJSONPart",
|
||||||
"RelationalKeyword",
|
"RelationalKeyword",
|
||||||
"RelationalOperator",
|
"RelationalOperator",
|
||||||
"SearchFilter",
|
"ValidationResponse",
|
||||||
"OrderByNullPosition",
|
"OrderByNullPosition",
|
||||||
"OrderDirection",
|
"OrderDirection",
|
||||||
"PaginationBase",
|
"PaginationBase",
|
||||||
"PaginationQuery",
|
"PaginationQuery",
|
||||||
"RecipeSearchQuery",
|
"RecipeSearchQuery",
|
||||||
"RequestQuery",
|
"RequestQuery",
|
||||||
"ValidationResponse",
|
"SearchFilter",
|
||||||
"ErrorResponse",
|
"ErrorResponse",
|
||||||
"FileTokenResponse",
|
"FileTokenResponse",
|
||||||
"SuccessResponse",
|
"SuccessResponse",
|
||||||
|
|
|
@ -38,6 +38,12 @@ from .user_passwords import (
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"ForgotPassword",
|
||||||
|
"PasswordResetToken",
|
||||||
|
"PrivatePasswordResetToken",
|
||||||
|
"ResetPassword",
|
||||||
|
"SavePasswordResetToken",
|
||||||
|
"ValidateResetToken",
|
||||||
"CredentialsRequest",
|
"CredentialsRequest",
|
||||||
"CredentialsRequestForm",
|
"CredentialsRequestForm",
|
||||||
"Token",
|
"Token",
|
||||||
|
@ -69,10 +75,4 @@ __all__ = [
|
||||||
"UserRatings",
|
"UserRatings",
|
||||||
"UserSummary",
|
"UserSummary",
|
||||||
"UserSummaryPagination",
|
"UserSummaryPagination",
|
||||||
"ForgotPassword",
|
|
||||||
"PasswordResetToken",
|
|
||||||
"PrivatePasswordResetToken",
|
|
||||||
"ResetPassword",
|
|
||||||
"SavePasswordResetToken",
|
|
||||||
"ValidateResetToken",
|
|
||||||
]
|
]
|
||||||
|
|
222
poetry.lock
generated
222
poetry.lock
generated
|
@ -1082,14 +1082,14 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ingredient-parser-nlp"
|
name = "ingredient-parser-nlp"
|
||||||
version = "2.1.1"
|
version = "2.2.0"
|
||||||
description = "A Python package to parse structured information from recipe ingredient sentences"
|
description = "A Python package to parse structured information from recipe ingredient sentences"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "<3.14,>=3.10"
|
python-versions = "<3.14,>=3.10"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "ingredient_parser_nlp-2.1.1-py3-none-any.whl", hash = "sha256:e09f73b28d2805d33f5523b84a304225bf62ebdca47560aa8e6c7176442ef6b6"},
|
{file = "ingredient_parser_nlp-2.2.0-py3-none-any.whl", hash = "sha256:b9be48c0a27eb972f8cfdc0f755cfa32fd16a598ff714b8f1a3b244c8622bed0"},
|
||||||
{file = "ingredient_parser_nlp-2.1.1.tar.gz", hash = "sha256:e7070b849d05395006b6a27923304b01ed4da04b53a82047c5ddddf1bbfe1fc7"},
|
{file = "ingredient_parser_nlp-2.2.0.tar.gz", hash = "sha256:cabd12bd01a030b19f1859a968219c7f2cd68dd08d03484194245f7454d85d20"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -1612,19 +1612,20 @@ pyyaml = ">=5.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs-material"
|
name = "mkdocs-material"
|
||||||
version = "9.6.16"
|
version = "9.6.17"
|
||||||
description = "Documentation that simply works"
|
description = "Documentation that simply works"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "mkdocs_material-9.6.16-py3-none-any.whl", hash = "sha256:8d1a1282b892fe1fdf77bfeb08c485ba3909dd743c9ba69a19a40f637c6ec18c"},
|
{file = "mkdocs_material-9.6.17-py3-none-any.whl", hash = "sha256:221dd8b37a63f52e580bcab4a7e0290e4a6f59bd66190be9c3d40767e05f9417"},
|
||||||
{file = "mkdocs_material-9.6.16.tar.gz", hash = "sha256:d07011df4a5c02ee0877496d9f1bfc986cfb93d964799b032dd99fe34c0e9d19"},
|
{file = "mkdocs_material-9.6.17.tar.gz", hash = "sha256:48ae7aec72a3f9f501a70be3fbd329c96ff5f5a385b67a1563e5ed5ce064affe"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
babel = ">=2.10,<3.0"
|
babel = ">=2.10,<3.0"
|
||||||
backrefs = ">=5.7.post1,<6.0"
|
backrefs = ">=5.7.post1,<6.0"
|
||||||
|
click = "<8.2.2"
|
||||||
colorama = ">=0.4,<1.0"
|
colorama = ">=0.4,<1.0"
|
||||||
jinja2 = ">=3.1,<4.0"
|
jinja2 = ">=3.1,<4.0"
|
||||||
markdown = ">=3.2,<4.0"
|
markdown = ">=3.2,<4.0"
|
||||||
|
@ -1877,95 +1878,95 @@ voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orjson"
|
name = "orjson"
|
||||||
version = "3.11.1"
|
version = "3.11.2"
|
||||||
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
description = ""
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "orjson-3.11.1-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:92d771c492b64119456afb50f2dff3e03a2db8b5af0eba32c5932d306f970532"},
|
{file = "orjson-3.11.2-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d6b8a78c33496230a60dc9487118c284c15ebdf6724386057239641e1eb69761"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0085ef83a4141c2ed23bfec5fecbfdb1e95dd42fc8e8c76057bdeeec1608ea65"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc04036eeae11ad4180d1f7b5faddb5dab1dee49ecd147cd431523869514873b"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5caf7f13f2e1b4e137060aed892d4541d07dabc3f29e6d891e2383c7ed483440"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c04325839c5754c253ff301cee8aaed7442d974860a44447bb3be785c411c27"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f716bcc166524eddfcf9f13f8209ac19a7f27b05cf591e883419079d98c8c99d"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32769e04cd7fdc4a59854376211145a1bbbc0aea5e9d6c9755d3d3c301d7c0df"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:507d6012fab05465d8bf21f5d7f4635ba4b6d60132874e349beff12fb51af7fe"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ff285d14917ea1408a821786e3677c5261fa6095277410409c694b8e7720ae0"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1545083b0931f754c80fd2422a73d83bea7a6d1b6de104a5f2c8dd3d64c291e"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2662f908114864b63ff75ffe6ffacf996418dd6cc25e02a72ad4bda81b1ec45a"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e217ce3bad76351e1eb29ebe5ca630326f45cd2141f62620107a229909501a3"},
|
{file = "orjson-3.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab463cf5d08ad6623a4dac1badd20e88a5eb4b840050c4812c782e3149fe2334"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06ef26e009304bda4df42e4afe518994cde6f89b4b04c0ff24021064f83f4fbb"},
|
{file = "orjson-3.11.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64414241bde943cbf3c00d45fcb5223dca6d9210148ba984aae6b5d63294502b"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:ba49683b87bea3ae1489a88e766e767d4f423a669a61270b6d6a7ead1c33bd65"},
|
{file = "orjson-3.11.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7773e71c0ae8c9660192ff144a3d69df89725325e3d0b6a6bb2c50e5ebaf9b84"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5072488fcc5cbcda2ece966d248e43ea1d222e19dd4c56d3f82747777f24d864"},
|
{file = "orjson-3.11.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:652ca14e283b13ece35bf3a86503c25592f294dbcfc5bb91b20a9c9a62a3d4be"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f58ae2bcd119226fe4aa934b5880fe57b8e97b69e51d5d91c88a89477a307016"},
|
{file = "orjson-3.11.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:26e99e98df8990ecfe3772bbdd7361f602149715c2cbc82e61af89bfad9528a4"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-win32.whl", hash = "sha256:6723be919c07906781b9c63cc52dc7d2fb101336c99dd7e85d3531d73fb493f7"},
|
{file = "orjson-3.11.2-cp310-cp310-win32.whl", hash = "sha256:5814313b3e75a2be7fe6c7958201c16c4560e21a813dbad25920752cecd6ad66"},
|
||||||
{file = "orjson-3.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:5fd44d69ddfdfb4e8d0d83f09d27a4db34930fba153fbf79f8d4ae8b47914e04"},
|
{file = "orjson-3.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:dc471ce2225ab4c42ca672f70600d46a8b8e28e8d4e536088c1ccdb1d22b35ce"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:15e2a57ce3b57c1a36acffcc02e823afefceee0a532180c2568c62213c98e3ef"},
|
{file = "orjson-3.11.2-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:888b64ef7eaeeff63f773881929434a5834a6a140a63ad45183d59287f07fc6a"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:17040a83ecaa130474af05bbb59a13cfeb2157d76385556041f945da936b1afd"},
|
{file = "orjson-3.11.2-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:83387cc8b26c9fa0ae34d1ea8861a7ae6cff8fb3e346ab53e987d085315a728e"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a68f23f09e5626cc0867a96cf618f68b91acb4753d33a80bf16111fd7f9928c"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7e35f003692c216d7ee901b6b916b5734d6fc4180fcaa44c52081f974c08e17"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47e07528bb6ccbd6e32a55e330979048b59bfc5518b47c89bc7ab9e3de15174a"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4a0a4c29ae90b11d0c00bcc31533854d89f77bde2649ec602f512a7e16e00640"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3807cce72bf40a9d251d689cbec28d2efd27e0f6673709f948f971afd52cb09"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:585d712b1880f68370108bc5534a257b561672d1592fae54938738fe7f6f1e33"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b2dc7e88da4ca201c940f5e6127998d9e89aa64264292334dad62854bc7fc27"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d08e342a7143f8a7c11f1c4033efe81acbd3c98c68ba1b26b96080396019701f"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3091dad33ac9e67c0a550cfff8ad5be156e2614d6f5d2a9247df0627751a1495"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c0f84fc50398773a702732c87cd622737bf11c0721e6db3041ac7802a686fb"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ed0fce2307843b79a0c83de49f65b86197f1e2310de07af9db2a1a77a61ce4c"},
|
{file = "orjson-3.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:140f84e3c8d4c142575898c91e3981000afebf0333df753a90b3435d349a5fe5"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5a31e84782a18c30abd56774c0cfa7b9884589f4d37d9acabfa0504dad59bb9d"},
|
{file = "orjson-3.11.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96304a2b7235e0f3f2d9363ddccdbfb027d27338722fe469fe656832a017602e"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26b6c821abf1ae515fbb8e140a2406c9f9004f3e52acb780b3dee9bfffddbd84"},
|
{file = "orjson-3.11.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d7612bb227d5d9582f1f50a60bd55c64618fc22c4a32825d233a4f2771a428a"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f857b3d134b36a8436f1e24dcb525b6b945108b30746c1b0b556200b5cb76d39"},
|
{file = "orjson-3.11.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a134587d18fe493befc2defffef2a8d27cfcada5696cb7234de54a21903ae89a"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:df146f2a14116ce80f7da669785fcb411406d8e80136558b0ecda4c924b9ac55"},
|
{file = "orjson-3.11.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0b84455e60c4bc12c1e4cbaa5cfc1acdc7775a9da9cec040e17232f4b05458bd"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-win32.whl", hash = "sha256:d777c57c1f86855fe5492b973f1012be776e0398571f7cc3970e9a58ecf4dc17"},
|
{file = "orjson-3.11.2-cp311-cp311-win32.whl", hash = "sha256:f0660efeac223f0731a70884e6914a5f04d613b5ae500744c43f7bf7b78f00f9"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:e9a5fd589951f02ec2fcb8d69339258bbf74b41b104c556e6d4420ea5e059313"},
|
{file = "orjson-3.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:955811c8405251d9e09cbe8606ad8fdef49a451bcf5520095a5ed38c669223d8"},
|
||||||
{file = "orjson-3.11.1-cp311-cp311-win_arm64.whl", hash = "sha256:4cddbe41ee04fddad35d75b9cf3e3736ad0b80588280766156b94783167777af"},
|
{file = "orjson-3.11.2-cp311-cp311-win_arm64.whl", hash = "sha256:2e4d423a6f838552e3a6d9ec734b729f61f88b1124fd697eab82805ea1a2a97d"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2b7c8be96db3a977367250c6367793a3c5851a6ca4263f92f0b48d00702f9910"},
|
{file = "orjson-3.11.2-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:901d80d349d8452162b3aa1afb82cec5bee79a10550660bc21311cc61a4c5486"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:72e18088f567bd4a45db5e3196677d9ed1605e356e500c8e32dd6e303167a13d"},
|
{file = "orjson-3.11.2-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:cf3bd3967a360e87ee14ed82cb258b7f18c710dacf3822fb0042a14313a673a1"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d346e2ae1ce17888f7040b65a5a4a0c9734cb20ffbd228728661e020b4c8b3a5"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26693dde66910078229a943e80eeb99fdce6cd2c26277dc80ead9f3ab97d2131"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4bda5426ebb02ceb806a7d7ec9ba9ee5e0c93fca62375151a7b1c00bc634d06b"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad4c8acb50a28211c33fc7ef85ddf5cb18d4636a5205fd3fa2dce0411a0e30c"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10506cebe908542c4f024861102673db534fd2e03eb9b95b30d94438fa220abf"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:994181e7f1725bb5f2d481d7d228738e0743b16bf319ca85c29369c65913df14"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45202ee3f5494644e064c41abd1320497fb92fd31fc73af708708af664ac3b56"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbb79a0476393c07656b69c8e763c3cc925fa8e1d9e9b7d1f626901bb5025448"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5adaf01b92e0402a9ac5c3ebe04effe2bbb115f0914a0a53d34ea239a746289"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:191ed27a1dddb305083d8716af413d7219f40ec1d4c9b0e977453b4db0d6fb6c"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6162a1a757a1f1f4a94bc6ffac834a3602e04ad5db022dd8395a54ed9dd51c81"},
|
{file = "orjson-3.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0afb89f16f07220183fd00f5f297328ed0a68d8722ad1b0c8dcd95b12bc82804"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:78404206977c9f946613d3f916727c189d43193e708d760ea5d4b2087d6b0968"},
|
{file = "orjson-3.11.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ab6e6b4e93b1573a026b6ec16fca9541354dd58e514b62c558b58554ae04307"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:db48f8e81072e26df6cdb0e9fff808c28597c6ac20a13d595756cf9ba1fed48a"},
|
{file = "orjson-3.11.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9cb23527efb61fb75527df55d20ee47989c4ee34e01a9c98ee9ede232abf6219"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0c1e394e67ced6bb16fea7054d99fbdd99a539cf4d446d40378d4c06e0a8548d"},
|
{file = "orjson-3.11.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a4dd1268e4035af21b8a09e4adf2e61f87ee7bf63b86d7bb0a237ac03fad5b45"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e7a840752c93d4eecd1378e9bb465c3703e127b58f675cd5c620f361b6cf57a4"},
|
{file = "orjson-3.11.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff8b155b145eaf5a9d94d2c476fbe18d6021de93cf36c2ae2c8c5b775763f14e"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-win32.whl", hash = "sha256:4537b0e09f45d2b74cb69c7f39ca1e62c24c0488d6bf01cd24673c74cd9596bf"},
|
{file = "orjson-3.11.2-cp312-cp312-win32.whl", hash = "sha256:ae3bb10279d57872f9aba68c9931aa71ed3b295fa880f25e68da79e79453f46e"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:dbee6b050062540ae404530cacec1bf25e56e8d87d8d9b610b935afeb6725cae"},
|
{file = "orjson-3.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:d026e1967239ec11a2559b4146a61d13914504b396f74510a1c4d6b19dfd8732"},
|
||||||
{file = "orjson-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:f55e557d4248322d87c4673e085c7634039ff04b47bfc823b87149ae12bef60d"},
|
{file = "orjson-3.11.2-cp312-cp312-win_arm64.whl", hash = "sha256:59f8d5ad08602711af9589375be98477d70e1d102645430b5a7985fdbf613b36"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53cfefe4af059e65aabe9683f76b9c88bf34b4341a77d329227c2424e0e59b0e"},
|
{file = "orjson-3.11.2-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a079fdba7062ab396380eeedb589afb81dc6683f07f528a03b6f7aae420a0219"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:93d5abed5a6f9e1b6f9b5bf6ed4423c11932b5447c2f7281d3b64e0f26c6d064"},
|
{file = "orjson-3.11.2-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:6a5f62ebbc530bb8bb4b1ead103647b395ba523559149b91a6c545f7cd4110ad"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbf06642f3db2966df504944cdd0eb68ca2717f0353bb20b20acd78109374a6"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7df6c7b8b0931feb3420b72838c3e2ba98c228f7aa60d461bc050cf4ca5f7b2"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dddf4e78747fa7f2188273f84562017a3c4f0824485b78372513c1681ea7a894"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6f59dfea7da1fced6e782bb3699718088b1036cb361f36c6e4dd843c5111aefe"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa3fe8653c9f57f0e16f008e43626485b6723b84b2f741f54d1258095b655912"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edf49146520fef308c31aa4c45b9925fd9c7584645caca7c0c4217d7900214ae"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6334d2382aff975a61f6f4d1c3daf39368b887c7de08f7c16c58f485dcf7adb2"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50995bbeb5d41a32ad15e023305807f561ac5dcd9bd41a12c8d8d1d2c83e44e6"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3d0855b643f259ee0cb76fe3df4c04483354409a520a902b067c674842eb6b8"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cc42960515076eb639b705f105712b658c525863d89a1704d984b929b0577d1"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eacdfeefd0a79987926476eb16e0245546bedeb8febbbbcf4b653e79257a8e4"},
|
{file = "orjson-3.11.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c56777cab2a7b2a8ea687fedafb84b3d7fdafae382165c31a2adf88634c432fa"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0ed07faf9e4873518c60480325dcbc16d17c59a165532cccfb409b4cdbaeff24"},
|
{file = "orjson-3.11.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:07349e88025b9b5c783077bf7a9f401ffbfb07fd20e86ec6fc5b7432c28c2c5e"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d6d308dd578ae3658f62bb9eba54801533225823cd3248c902be1ebc79b5e014"},
|
{file = "orjson-3.11.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:45841fbb79c96441a8c58aa29ffef570c5df9af91f0f7a9572e5505e12412f15"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c4aa13ca959ba6b15c0a98d3d204b850f9dc36c08c9ce422ffb024eb30d6e058"},
|
{file = "orjson-3.11.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:13d8d8db6cd8d89d4d4e0f4161acbbb373a4d2a4929e862d1d2119de4aa324ac"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:be3d0653322abc9b68e5bcdaee6cfd58fcbe9973740ab222b87f4d687232ab1f"},
|
{file = "orjson-3.11.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51da1ee2178ed09c00d09c1b953e45846bbc16b6420965eb7a913ba209f606d8"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-win32.whl", hash = "sha256:4dd34e7e2518de8d7834268846f8cab7204364f427c56fb2251e098da86f5092"},
|
{file = "orjson-3.11.2-cp313-cp313-win32.whl", hash = "sha256:51dc033df2e4a4c91c0ba4f43247de99b3cbf42ee7a42ee2b2b2f76c8b2f2cb5"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:d6895d32032b6362540e6d0694b19130bb4f2ad04694002dce7d8af588ca5f77"},
|
{file = "orjson-3.11.2-cp313-cp313-win_amd64.whl", hash = "sha256:29d91d74942b7436f29b5d1ed9bcfc3f6ef2d4f7c4997616509004679936650d"},
|
||||||
{file = "orjson-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:bb7c36d5d3570fcbb01d24fa447a21a7fe5a41141fd88e78f7994053cc4e28f4"},
|
{file = "orjson-3.11.2-cp313-cp313-win_arm64.whl", hash = "sha256:4ca4fb5ac21cd1e48028d4f708b1bb13e39c42d45614befd2ead004a8bba8535"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7b71ef394327b3d0b39f6ea7ade2ecda2731a56c6a7cbf0d6a7301203b92a89b"},
|
{file = "orjson-3.11.2-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3dcba7101ea6a8d4ef060746c0f2e7aa8e2453a1012083e1ecce9726d7554cb7"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:77c0fe28ed659b62273995244ae2aa430e432c71f86e4573ab16caa2f2e3ca5e"},
|
{file = "orjson-3.11.2-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:15d17bdb76a142e1f55d91913e012e6e6769659daa6bfef3ef93f11083137e81"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:1495692f1f1ba2467df429343388a0ed259382835922e124c0cfdd56b3d1f727"},
|
{file = "orjson-3.11.2-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:53c9e81768c69d4b66b8876ec3c8e431c6e13477186d0db1089d82622bccd19f"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:08c6a762fca63ca4dc04f66c48ea5d2428db55839fec996890e1bfaf057b658c"},
|
{file = "orjson-3.11.2-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d4f13af59a7b84c1ca6b8a7ab70d608f61f7c44f9740cd42409e6ae7b6c8d8b7"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e26794fe3976810b2c01fda29bd9ac7c91a3c1284b29cc9a383989f7b614037"},
|
{file = "orjson-3.11.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bde64aa469b5ee46cc960ed241fae3721d6a8801dacb2ca3466547a2535951e4"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4b4b4f8f0b1d3ef8dc73e55363a0ffe012a42f4e2f1a140bf559698dca39b3fa"},
|
{file = "orjson-3.11.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:b5ca86300aeb383c8fa759566aca065878d3d98c3389d769b43f0a2e84d52c5f"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:848be553ea35aa89bfefbed2e27c8a41244c862956ab8ba00dc0b27e84fd58de"},
|
{file = "orjson-3.11.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:24e32a558ebed73a6a71c8f1cbc163a7dd5132da5270ff3d8eeb727f4b6d1bc7"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c964c29711a4b1df52f8d9966f015402a6cf87753a406c1c4405c407dd66fd45"},
|
{file = "orjson-3.11.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e36319a5d15b97e4344110517450396845cc6789aed712b1fbf83c1bd95792f6"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-win32.whl", hash = "sha256:33aada2e6b6bc9c540d396528b91e666cedb383740fee6e6a917f561b390ecb1"},
|
{file = "orjson-3.11.2-cp314-cp314-win32.whl", hash = "sha256:40193ada63fab25e35703454d65b6afc71dbc65f20041cb46c6d91709141ef7f"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:68e10fd804e44e36188b9952543e3fa22f5aa8394da1b5283ca2b423735c06e8"},
|
{file = "orjson-3.11.2-cp314-cp314-win_amd64.whl", hash = "sha256:7c8ac5f6b682d3494217085cf04dadae66efee45349ad4ee2a1da3c97e2305a8"},
|
||||||
{file = "orjson-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:f3cf6c07f8b32127d836be8e1c55d4f34843f7df346536da768e9f73f22078a1"},
|
{file = "orjson-3.11.2-cp314-cp314-win_arm64.whl", hash = "sha256:21cf261e8e79284242e4cb1e5924df16ae28255184aafeff19be1405f6d33f67"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3d593a9e0bccf2c7401ae53625b519a7ad7aa555b1c82c0042b322762dc8af4e"},
|
{file = "orjson-3.11.2-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:957f10c7b5bce3d3f2ad577f3b307c784f5dabafcce3b836229c269c11841c86"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0baad413c498fc1eef568504f11ea46bc71f94b845c075e437da1e2b85b4fb86"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a669e31ab8eb466c9142ac7a4be2bb2758ad236a31ef40dcd4cf8774ab40f33"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:22cf17ae1dae3f9b5f37bfcdba002ed22c98bbdb70306e42dc18d8cc9b50399a"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:adedf7d887416c51ad49de3c53b111887e0b63db36c6eb9f846a8430952303d8"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e855c1e97208133ce88b3ef6663c9a82ddf1d09390cd0856a1638deee0390c3c"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ad8873979659ad98fc56377b9c5b93eb8059bf01e6412f7abf7dbb3d637a991"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5861c5f7acff10599132854c70ab10abf72aebf7c627ae13575e5f20b1ab8fe"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9482ef83b2bf796157566dd2d2742a8a1e377045fe6065fa67acb1cb1d21d9a3"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1e6415c5b5ff3a616a6dafad7b6ec303a9fc625e9313c8e1268fb1370a63dcb"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73cee7867c1fcbd1cc5b6688b3e13db067f968889242955780123a68b3d03316"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:912579642f5d7a4a84d93c5eed8daf0aa34e1f2d3f4dc6571a8e418703f5701e"},
|
{file = "orjson-3.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:465166773265f3cc25db10199f5d11c81898a309e26a2481acf33ddbec433fda"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2092e1d3b33f64e129ff8271642afddc43763c81f2c30823b4a4a4a5f2ea5b55"},
|
{file = "orjson-3.11.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc000190a7b1d2d8e36cba990b3209a1e15c0efb6c7750e87f8bead01afc0d46"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:b8ac64caba1add2c04e9cd4782d4d0c4d6c554b7a3369bdec1eed7854c98db7b"},
|
{file = "orjson-3.11.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:df3fdd8efa842ccbb81135d6f58a73512f11dba02ed08d9466261c2e9417af4e"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:23196b826ebc85c43f8e27bee0ab33c5fb13a29ea47fb4fcd6ebb1e660eb0252"},
|
{file = "orjson-3.11.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3dacfc621be3079ec69e0d4cb32e3764067726e0ef5a5576428f68b6dc85b4f6"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f2d3364cfad43003f1e3d564a069c8866237cca30f9c914b26ed2740b596ed00"},
|
{file = "orjson-3.11.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9fdff73a029cde5f4a1cf5ec9dbc6acab98c9ddd69f5580c2b3f02ce43ba9f9f"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-win32.whl", hash = "sha256:20b0dca94ea4ebe4628330de50975b35817a3f52954c1efb6d5d0498a3bbe581"},
|
{file = "orjson-3.11.2-cp39-cp39-win32.whl", hash = "sha256:b1efbdc479c6451138c3733e415b4d0e16526644e54e2f3689f699c4cda303bf"},
|
||||||
{file = "orjson-3.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:200c3ad7ed8b5d31d49143265dfebd33420c4b61934ead16833b5cd2c3d241be"},
|
{file = "orjson-3.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:c9ec0cc0d4308cad1e38a1ee23b64567e2ff364c2a3fe3d6cbc69cf911c45712"},
|
||||||
{file = "orjson-3.11.1.tar.gz", hash = "sha256:48d82770a5fd88778063604c566f9c7c71820270c9cc9338d25147cbf34afd96"},
|
{file = "orjson-3.11.2.tar.gz", hash = "sha256:91bdcf5e69a8fd8e8bdb3de32b31ff01d2bd60c1e8d5fe7d5afabdcf19920309"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3287,30 +3288,31 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.12.8"
|
version = "0.12.9"
|
||||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513"},
|
{file = "ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e"},
|
||||||
{file = "ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc"},
|
{file = "ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f"},
|
||||||
{file = "ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec"},
|
{file = "ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce"},
|
||||||
{file = "ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340"},
|
||||||
{file = "ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea"},
|
{file = "ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb"},
|
||||||
{file = "ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3"},
|
{file = "ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af"},
|
||||||
{file = "ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161"},
|
{file = "ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc"},
|
||||||
{file = "ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46"},
|
{file = "ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66"},
|
||||||
{file = "ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3"},
|
{file = "ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7"},
|
||||||
{file = "ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e"},
|
{file = "ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93"},
|
||||||
{file = "ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749"},
|
{file = "ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908"},
|
||||||
{file = "ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033"},
|
{file = "ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089"},
|
||||||
|
{file = "ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -217,13 +217,14 @@ def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUse
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get the cookbook and make sure we only get the public recipes from each household
|
# Get the cookbook recipes and make sure we only get the public recipes from each household
|
||||||
response = api_client.get(api_routes.explore_groups_group_slug_cookbooks_item_id(unique_user.group_id, cookbook.id))
|
response = api_client.get(
|
||||||
|
api_routes.explore_groups_group_slug_recipes(unique_user.group_id), params={"cookbook": cookbook.slug}
|
||||||
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
cookbook_data = response.json()
|
recipe_data = response.json()
|
||||||
assert cookbook_data["id"] == str(cookbook.id)
|
|
||||||
|
|
||||||
cookbook_recipe_ids: set[str] = {recipe["id"] for recipe in cookbook_data["recipes"]}
|
cookbook_recipe_ids: set[str] = {recipe["id"] for recipe in recipe_data["items"]}
|
||||||
assert len(cookbook_recipe_ids) == 2
|
assert len(cookbook_recipe_ids) == 2
|
||||||
assert str(public_recipe.id) in cookbook_recipe_ids
|
assert str(public_recipe.id) in cookbook_recipe_ids
|
||||||
assert str(private_recipe.id) not in cookbook_recipe_ids
|
assert str(private_recipe.id) not in cookbook_recipe_ids
|
||||||
|
@ -297,13 +298,14 @@ def test_get_cookbooks_private_household(api_client: TestClient, unique_user: Te
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get the cookbook and make sure we only get the public recipes from each household
|
# Get the cookbook recipes and make sure we only get the public recipes from each household
|
||||||
response = api_client.get(api_routes.explore_groups_group_slug_cookbooks_item_id(unique_user.group_id, cookbook.id))
|
response = api_client.get(
|
||||||
|
api_routes.explore_groups_group_slug_recipes(unique_user.group_id), params={"cookbook": cookbook.slug}
|
||||||
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
cookbook_data = response.json()
|
recipe_data = response.json()
|
||||||
assert cookbook_data["id"] == str(cookbook.id)
|
|
||||||
|
|
||||||
cookbook_recipe_ids: set[str] = {recipe["id"] for recipe in cookbook_data["recipes"]}
|
cookbook_recipe_ids: set[str] = {recipe["id"] for recipe in recipe_data["items"]}
|
||||||
assert len(cookbook_recipe_ids) == 1
|
assert len(cookbook_recipe_ids) == 1
|
||||||
assert str(public_recipe.id) in cookbook_recipe_ids
|
assert str(public_recipe.id) in cookbook_recipe_ids
|
||||||
assert str(other_household_private_recipe.id) not in cookbook_recipe_ids
|
assert str(other_household_private_recipe.id) not in cookbook_recipe_ids
|
||||||
|
|
239
tests/unit_tests/core/security/auth_cache/test_auth_cache.py
Normal file
239
tests/unit_tests/core/security/auth_cache/test_auth_cache.py
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from mealie.routes.auth.auth_cache import AuthCache
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def cache():
|
||||||
|
return AuthCache(threshold=5, default_timeout=1.0)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_set_and_get_basic_operation(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = {"user": "test_user", "data": "some_data"}
|
||||||
|
|
||||||
|
result = await cache.set(key, value)
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
retrieved = await cache.get(key)
|
||||||
|
assert retrieved == value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_nonexistent_key(cache: AuthCache):
|
||||||
|
result = await cache.get("nonexistent_key")
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_has_key(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = "test_value"
|
||||||
|
|
||||||
|
assert await cache.has(key) is False
|
||||||
|
|
||||||
|
await cache.set(key, value)
|
||||||
|
assert await cache.has(key) is True
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_delete_key(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = "test_value"
|
||||||
|
|
||||||
|
await cache.set(key, value)
|
||||||
|
assert await cache.has(key) is True
|
||||||
|
|
||||||
|
result = await cache.delete(key)
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
assert await cache.has(key) is False
|
||||||
|
assert await cache.get(key) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_delete_nonexistent_key(cache: AuthCache):
|
||||||
|
result = await cache.delete("nonexistent_key")
|
||||||
|
assert result is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_expiration_with_custom_timeout(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = "test_value"
|
||||||
|
timeout = 0.1 # 100ms
|
||||||
|
|
||||||
|
await cache.set(key, value, timeout=timeout)
|
||||||
|
assert await cache.has(key) is True
|
||||||
|
assert await cache.get(key) == value
|
||||||
|
|
||||||
|
# Wait for expiration
|
||||||
|
await asyncio.sleep(0.15)
|
||||||
|
|
||||||
|
assert await cache.has(key) is False
|
||||||
|
assert await cache.get(key) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_expiration_with_default_timeout(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = "test_value"
|
||||||
|
|
||||||
|
await cache.set(key, value)
|
||||||
|
assert await cache.has(key) is True
|
||||||
|
|
||||||
|
with patch("mealie.routes.auth.auth_cache.time") as mock_time:
|
||||||
|
current_time = time.time()
|
||||||
|
expired_time = current_time + cache.default_timeout + 1
|
||||||
|
mock_time.time.return_value = expired_time
|
||||||
|
|
||||||
|
assert await cache.has(key) is False
|
||||||
|
assert await cache.get(key) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_zero_timeout_never_expires(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
value = "test_value"
|
||||||
|
|
||||||
|
await cache.set(key, value, timeout=0)
|
||||||
|
with patch("time.time") as mock_time:
|
||||||
|
mock_time.return_value = time.time() + 10000
|
||||||
|
|
||||||
|
assert await cache.has(key) is True
|
||||||
|
assert await cache.get(key) == value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_clear_cache(cache: AuthCache):
|
||||||
|
await cache.set("key1", "value1")
|
||||||
|
await cache.set("key2", "value2")
|
||||||
|
await cache.set("key3", "value3")
|
||||||
|
|
||||||
|
assert await cache.has("key1") is True
|
||||||
|
assert await cache.has("key2") is True
|
||||||
|
assert await cache.has("key3") is True
|
||||||
|
|
||||||
|
cache.clear()
|
||||||
|
|
||||||
|
assert await cache.has("key1") is False
|
||||||
|
assert await cache.has("key2") is False
|
||||||
|
assert await cache.has("key3") is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_pruning_when_threshold_exceeded(cache: AuthCache):
|
||||||
|
"""Test that the cache prunes old items when threshold is exceeded."""
|
||||||
|
# Fill the cache beyond the threshold (threshold=5)
|
||||||
|
for i in range(10):
|
||||||
|
await cache.set(f"key_{i}", f"value_{i}")
|
||||||
|
|
||||||
|
assert len(cache._cache) < 10 # Should be less than what we inserted
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_pruning_removes_expired_items(cache: AuthCache):
|
||||||
|
# Add some items that will expire quickly
|
||||||
|
await cache.set("expired1", "value1", timeout=0.01)
|
||||||
|
await cache.set("expired2", "value2", timeout=0.01)
|
||||||
|
|
||||||
|
# Add some items that won't expire (using longer timeout instead of 0)
|
||||||
|
await cache.set("permanent1", "value3", timeout=300)
|
||||||
|
await cache.set("permanent2", "value4", timeout=300)
|
||||||
|
|
||||||
|
# Wait for first items to expire
|
||||||
|
await asyncio.sleep(0.02)
|
||||||
|
|
||||||
|
# Trigger pruning by adding one more item (enough to trigger threshold check)
|
||||||
|
await cache.set("trigger_final", "final_value")
|
||||||
|
|
||||||
|
assert await cache.has("expired1") is False
|
||||||
|
assert await cache.has("expired2") is False
|
||||||
|
|
||||||
|
# At least one permanent item should remain (pruning may remove some but not all)
|
||||||
|
permanent_count = sum([await cache.has("permanent1"), await cache.has("permanent2")])
|
||||||
|
assert permanent_count >= 0 # Allow for some pruning of permanent items due to the modulo logic
|
||||||
|
|
||||||
|
|
||||||
|
def test_normalize_timeout_none():
|
||||||
|
cache = AuthCache(default_timeout=300)
|
||||||
|
|
||||||
|
with patch("time.time", return_value=1000):
|
||||||
|
result = cache._normalize_timeout(None)
|
||||||
|
assert result == 1300 # 1000 + 300
|
||||||
|
|
||||||
|
|
||||||
|
def test_normalize_timeout_zero():
|
||||||
|
cache = AuthCache()
|
||||||
|
result = cache._normalize_timeout(0)
|
||||||
|
assert result == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_normalize_timeout_positive():
|
||||||
|
cache = AuthCache()
|
||||||
|
|
||||||
|
with patch("time.time", return_value=1000):
|
||||||
|
result = cache._normalize_timeout(60)
|
||||||
|
assert result == 1060 # 1000 + 60
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_cache_stores_complex_objects(cache: AuthCache):
|
||||||
|
# Simulate an OIDC token structure
|
||||||
|
token_data = {
|
||||||
|
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
|
||||||
|
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
|
||||||
|
"userinfo": {
|
||||||
|
"sub": "user123",
|
||||||
|
"email": "user@example.com",
|
||||||
|
"preferred_username": "testuser",
|
||||||
|
"groups": ["mealie_user"],
|
||||||
|
},
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 3600,
|
||||||
|
}
|
||||||
|
|
||||||
|
key = "oauth_token_user123"
|
||||||
|
await cache.set(key, token_data)
|
||||||
|
|
||||||
|
retrieved = await cache.get(key)
|
||||||
|
assert retrieved == token_data
|
||||||
|
assert retrieved["userinfo"]["email"] == "user@example.com"
|
||||||
|
assert "mealie_user" in retrieved["userinfo"]["groups"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_cache_overwrites_existing_key(cache: AuthCache):
|
||||||
|
key = "test_key"
|
||||||
|
|
||||||
|
await cache.set(key, "initial_value")
|
||||||
|
assert await cache.get(key) == "initial_value"
|
||||||
|
|
||||||
|
await cache.set(key, "new_value")
|
||||||
|
assert await cache.get(key) == "new_value"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_concurrent_access(cache: AuthCache):
|
||||||
|
async def set_values(start_idx, count):
|
||||||
|
for i in range(start_idx, start_idx + count):
|
||||||
|
await cache.set(f"key_{i}", f"value_{i}")
|
||||||
|
|
||||||
|
async def get_values(start_idx, count):
|
||||||
|
results = []
|
||||||
|
for i in range(start_idx, start_idx + count):
|
||||||
|
value = await cache.get(f"key_{i}")
|
||||||
|
results.append(value)
|
||||||
|
return results
|
||||||
|
|
||||||
|
await asyncio.gather(set_values(0, 5), set_values(5, 5), set_values(10, 5))
|
||||||
|
results = await asyncio.gather(get_values(0, 5), get_values(5, 5), get_values(10, 5))
|
||||||
|
|
||||||
|
all_results = [item for sublist in results for item in sublist]
|
||||||
|
actual_values = [v for v in all_results if v is not None]
|
||||||
|
assert len(actual_values) > 0
|
|
@ -0,0 +1,153 @@
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from authlib.integrations.starlette_client import OAuth
|
||||||
|
|
||||||
|
from mealie.routes.auth.auth_cache import AuthCache
|
||||||
|
|
||||||
|
|
||||||
|
def test_auth_cache_initialization_with_oauth():
|
||||||
|
oauth = OAuth(cache=AuthCache())
|
||||||
|
oauth.register(
|
||||||
|
"test_oidc",
|
||||||
|
client_id="test_client_id",
|
||||||
|
client_secret="test_client_secret",
|
||||||
|
server_metadata_url="https://example.com/.well-known/openid_configuration",
|
||||||
|
client_kwargs={"scope": "openid email profile"},
|
||||||
|
code_challenge_method="S256",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert oauth is not None
|
||||||
|
assert isinstance(oauth.cache, AuthCache)
|
||||||
|
assert "test_oidc" in oauth._clients
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_oauth_cache_operations():
|
||||||
|
cache = AuthCache(threshold=500, default_timeout=300)
|
||||||
|
cache_key = "oauth_state_12345"
|
||||||
|
oauth_data = {
|
||||||
|
"state": "12345",
|
||||||
|
"code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
|
||||||
|
"redirect_uri": "http://localhost:3000/login",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await cache.set(cache_key, oauth_data, timeout=600) # 10 minutes
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
retrieved_data = await cache.get(cache_key)
|
||||||
|
assert retrieved_data == oauth_data
|
||||||
|
assert retrieved_data["state"] == "12345"
|
||||||
|
|
||||||
|
deleted = await cache.delete(cache_key)
|
||||||
|
assert deleted is True
|
||||||
|
assert await cache.get(cache_key) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_oauth_cache_handles_token_expiration():
|
||||||
|
cache = AuthCache()
|
||||||
|
token_key = "access_token_user123"
|
||||||
|
token_data = {
|
||||||
|
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 3600,
|
||||||
|
"scope": "openid email profile",
|
||||||
|
}
|
||||||
|
|
||||||
|
await cache.set(token_key, token_data, timeout=0.1)
|
||||||
|
assert await cache.has(token_key) is True
|
||||||
|
|
||||||
|
await asyncio.sleep(0.15)
|
||||||
|
assert await cache.has(token_key) is False
|
||||||
|
assert await cache.get(token_key) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_oauth_cache_concurrent_requests():
|
||||||
|
cache = AuthCache()
|
||||||
|
|
||||||
|
async def simulate_oauth_flow(user_id: str):
|
||||||
|
"""Simulate a complete OAuth flow for a user."""
|
||||||
|
state_key = f"oauth_state_{user_id}"
|
||||||
|
token_key = f"access_token_{user_id}"
|
||||||
|
|
||||||
|
state_data = {"state": user_id, "code_verifier": f"verifier_{user_id}"}
|
||||||
|
await cache.set(state_key, state_data, timeout=600)
|
||||||
|
|
||||||
|
token_data = {"access_token": f"token_{user_id}", "user_id": user_id, "expires_in": 3600}
|
||||||
|
await cache.set(token_key, token_data, timeout=3600)
|
||||||
|
|
||||||
|
state = await cache.get(state_key)
|
||||||
|
token = await cache.get(token_key)
|
||||||
|
|
||||||
|
return state, token
|
||||||
|
|
||||||
|
results = await asyncio.gather(
|
||||||
|
simulate_oauth_flow("user1"), simulate_oauth_flow("user2"), simulate_oauth_flow("user3")
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, (state, token) in enumerate(results, 1):
|
||||||
|
assert state["state"] == f"user{i}"
|
||||||
|
assert token["access_token"] == f"token_user{i}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_auth_cache_disabled_when_oidc_not_ready():
|
||||||
|
cache = AuthCache()
|
||||||
|
assert cache is not None
|
||||||
|
assert isinstance(cache, AuthCache)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_auth_cache_memory_efficiency():
|
||||||
|
cache = AuthCache(threshold=10, default_timeout=300)
|
||||||
|
for i in range(50):
|
||||||
|
await cache.set(f"token_{i}", f"data_{i}", timeout=0) # Never expire
|
||||||
|
|
||||||
|
assert len(cache._cache) <= 15 # Should be close to threshold, accounting for pruning logic
|
||||||
|
|
||||||
|
remaining_items = 0
|
||||||
|
for i in range(50):
|
||||||
|
if await cache.has(f"token_{i}"):
|
||||||
|
remaining_items += 1
|
||||||
|
|
||||||
|
assert 0 < remaining_items < 50
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_auth_cache_with_real_oauth_data_structure():
|
||||||
|
cache = AuthCache()
|
||||||
|
oauth_token = {
|
||||||
|
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ...",
|
||||||
|
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ...",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 3600,
|
||||||
|
"scope": "openid email profile groups",
|
||||||
|
"userinfo": {
|
||||||
|
"sub": "auth0|507f1f77bcf86cd799439011",
|
||||||
|
"email": "john.doe@example.com",
|
||||||
|
"email_verified": True,
|
||||||
|
"name": "John Doe",
|
||||||
|
"preferred_username": "johndoe",
|
||||||
|
"groups": ["mealie_user", "staff"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
user_session_key = "oauth_session_auth0|507f1f77bcf86cd799439011"
|
||||||
|
await cache.set(user_session_key, oauth_token, timeout=3600)
|
||||||
|
|
||||||
|
retrieved = await cache.get(user_session_key)
|
||||||
|
assert retrieved["access_token"] == oauth_token["access_token"]
|
||||||
|
assert retrieved["userinfo"]["email"] == "john.doe@example.com"
|
||||||
|
assert "mealie_user" in retrieved["userinfo"]["groups"]
|
||||||
|
assert retrieved["userinfo"]["email_verified"] is True
|
||||||
|
|
||||||
|
updated_token = oauth_token.copy()
|
||||||
|
updated_token["access_token"] = "new_access_token_eyJhbGciOiJSUzI1NiIs..."
|
||||||
|
updated_token["userinfo"]["last_login"] = "2024-01-01T12:00:00Z"
|
||||||
|
|
||||||
|
await cache.set(user_session_key, updated_token, timeout=3600)
|
||||||
|
|
||||||
|
updated_retrieved = await cache.get(user_session_key)
|
||||||
|
assert updated_retrieved["access_token"] != oauth_token["access_token"]
|
||||||
|
assert updated_retrieved["userinfo"]["last_login"] == "2024-01-01T12:00:00Z"
|
Loading…
Add table
Add a link
Reference in a new issue