chore: Nuxt 4 upgrade (#7426)

This commit is contained in:
Kuchenpirat
2026-04-08 17:25:41 +02:00
committed by GitHub
parent 70a251a331
commit d3e41582ae
561 changed files with 1840 additions and 2750 deletions

View File

@@ -1,30 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { AdminAboutInfo, CheckAppConfig } from "~/lib/api/types/admin";
const prefix = "/api";
const routes = {
about: `${prefix}/admin/about`,
aboutStatistics: `${prefix}/admin/about/statistics`,
check: `${prefix}/admin/about/check`,
docker: `${prefix}/admin/about/docker/validate`,
validationFile: `${prefix}/media/docker/validate.txt`,
};
export class AdminAboutAPI extends BaseAPI {
async about() {
return await this.requests.get<AdminAboutInfo>(routes.about);
}
async statistics() {
return await this.requests.get(routes.aboutStatistics);
}
async checkApp() {
return await this.requests.get<CheckAppConfig>(routes.check);
}
async getDockerValidateFileContents() {
return await this.requests.get<string>(routes.validationFile);
}
}

View File

@@ -1,14 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { MealieAnalytics } from "~/lib/api/types/analytics";
const prefix = "/api";
const routes = {
base: `${prefix}/admin/analytics`,
};
export class AdminAnalyticsApi extends BaseAPI {
async getAnalytics() {
return await this.requests.get<MealieAnalytics>(routes.base);
}
}

View File

@@ -1,33 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { AllBackups } from "~/lib/api/types/admin";
import type { ErrorResponse, FileTokenResponse, SuccessResponse } from "~/lib/api/types/response";
const prefix = "/api";
const routes = {
base: `${prefix}/admin/backups`,
item: (name: string) => `${prefix}/admin/backups/${name}`,
restore: (name: string) => `${prefix}/admin/backups/${name}/restore`,
};
export class AdminBackupsApi extends BaseAPI {
async getAll() {
return await this.requests.get<AllBackups>(routes.base);
}
async create() {
return await this.requests.post<SuccessResponse | ErrorResponse>(routes.base, {});
}
async get(fileName: string) {
return await this.requests.get<FileTokenResponse>(routes.item(fileName));
}
async delete(fileName: string) {
return await this.requests.delete<SuccessResponse | ErrorResponse>(routes.item(fileName));
}
async restore(fileName: string) {
return await this.requests.post<SuccessResponse | ErrorResponse>(routes.restore(fileName), {});
}
}

View File

@@ -1,21 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { DebugResponse } from "~/lib/api/types/admin";
const prefix = "/api";
const routes = {
openai: `${prefix}/admin/debug/openai`,
};
export class AdminDebugAPI extends BaseAPI {
async debugOpenAI(fileObject: Blob | File | undefined = undefined, fileName = "") {
let formData: FormData | null = null;
if (fileObject) {
formData = new FormData();
formData.append("image", fileObject);
formData.append("extension", fileName.split(".").pop() ?? "");
}
return await this.requests.post<DebugResponse>(routes.openai, formData);
}
}

View File

@@ -1,20 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { GroupBase, GroupInDB } from "~/lib/api/types/user";
import type { GroupAdminUpdate } from "~/lib/api/types/group";
const prefix = "/api";
const routes = {
adminUsers: `${prefix}/admin/groups`,
adminUsersId: (id: string) => `${prefix}/admin/groups/${id}`,
};
export class AdminGroupsApi extends BaseCRUDAPI<GroupBase, GroupInDB, GroupAdminUpdate> {
baseRoute: string = routes.adminUsers;
itemRoute = routes.adminUsersId;
async updateOne(id: string, payload: GroupAdminUpdate) {
// TODO: This should probably be a patch request, which isn't offered by the API currently
return await this.requests.put<GroupInDB, GroupAdminUpdate>(this.itemRoute(id), payload);
}
}

View File

@@ -1,14 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { HouseholdCreate, HouseholdInDB, UpdateHouseholdAdmin } from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
adminHouseholds: `${prefix}/admin/households`,
adminHouseholdsId: (id: string) => `${prefix}/admin/households/${id}`,
};
export class AdminHouseholdsApi extends BaseCRUDAPI<HouseholdCreate, HouseholdInDB, UpdateHouseholdAdmin> {
baseRoute: string = routes.adminHouseholds;
itemRoute = routes.adminHouseholdsId;
}

View File

@@ -1,45 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { SuccessResponse } from "~/lib/api/types/response";
import type { MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary } from "~/lib/api/types/admin";
const prefix = "/api";
const routes = {
base: `${prefix}/admin/maintenance`,
storage: `${prefix}/admin/maintenance/storage`,
logs: (lines: number) => `${prefix}/admin/maintenance/logs?lines=${lines}`,
cleanTemp: `${prefix}/admin/maintenance/clean/temp`,
cleanImages: `${prefix}/admin/maintenance/clean/images`,
cleanRecipeFolders: `${prefix}/admin/maintenance/clean/recipe-folders`,
cleanLogFile: `${prefix}/admin/maintenance/clean/logs`,
};
export class AdminMaintenanceApi extends BaseAPI {
async getInfo() {
return this.requests.get<MaintenanceSummary>(routes.base);
}
async getStorageDetails() {
return await this.requests.get<MaintenanceStorageDetails>(routes.storage);
}
async cleanTemp() {
return await this.requests.post<SuccessResponse>(routes.cleanTemp, {});
}
async cleanImages() {
return await this.requests.post<SuccessResponse>(routes.cleanImages, {});
}
async cleanRecipeFolders() {
return await this.requests.post<SuccessResponse>(routes.cleanRecipeFolders, {});
}
async cleanLogFile() {
return await this.requests.post<SuccessResponse>(routes.cleanLogFile, {});
}
async logs(lines: number) {
return await this.requests.get<MaintenanceLogs>(routes.logs(lines));
}
}

View File

@@ -1,24 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { ForgotPassword, PasswordResetToken, UnlockResults, UserIn, UserOut } from "~/lib/api/types/user";
const prefix = "/api";
const routes = {
adminUsers: `${prefix}/admin/users`,
adminUsersId: (tag: string) => `${prefix}/admin/users/${tag}`,
adminResetLockedUsers: (force: boolean) => `${prefix}/admin/users/unlock?force=${force ? "true" : "false"}`,
adminPasswordResetToken: `${prefix}/admin/users/password-reset-token`,
};
export class AdminUsersApi extends BaseCRUDAPI<UserIn, UserOut, UserOut> {
baseRoute: string = routes.adminUsers;
itemRoute = routes.adminUsersId;
async unlockAllUsers(force = false) {
return await this.requests.post<UnlockResults>(routes.adminResetLockedUsers(force), {});
}
async generatePasswordResetToken(payload: ForgotPassword) {
return await this.requests.post<PasswordResetToken>(routes.adminPasswordResetToken, payload);
}
}

View File

@@ -1,81 +0,0 @@
import type { Recipe } from "../types/recipe";
import type { ApiRequestInstance, PaginationData } from "~/lib/api/types/non-generated";
import { type QueryValue, route } from "~/lib/api/base/route";
export interface CrudAPIInterface {
requests: ApiRequestInstance;
// Route Properties / Methods
baseRoute: string;
itemRoute(itemId: string | number): string;
// Methods
}
export abstract class BaseAPI {
requests: ApiRequestInstance;
constructor(requests: ApiRequestInstance) {
this.requests = requests;
}
}
export abstract class BaseCRUDAPIReadOnly<ReadType>
extends BaseAPI
implements CrudAPIInterface {
public baseRoute: string;
public itemRouteFn: (itemId: string | number) => string;
constructor(
requests: ApiRequestInstance,
baseRoute: string,
itemRoute: (itemId: string | number) => string,
) {
super(requests);
this.baseRoute = baseRoute;
this.itemRouteFn = itemRoute;
}
get baseRouteValue() {
return this.baseRoute;
}
itemRoute(itemId: string | number): string {
return this.itemRouteFn(itemId);
}
async getAll(page = 1, perPage = -1, params = {} as Record<string, QueryValue>) {
params = Object.fromEntries(Object.entries(params).filter(([_, v]) => v !== null && v !== undefined));
return await this.requests.get<PaginationData<ReadType>>(route(this.baseRoute, { page, perPage, ...params }));
}
async getOne(itemId: string | number) {
return await this.requests.get<ReadType>(this.itemRoute(itemId));
}
}
export abstract class BaseCRUDAPI<CreateType, ReadType, UpdateType = CreateType>
extends BaseCRUDAPIReadOnly<ReadType>
implements CrudAPIInterface {
async createOne(payload: CreateType) {
return await this.requests.post<ReadType>(this.baseRoute, payload);
}
async updateOne(itemId: string | number, payload: UpdateType) {
return await this.requests.put<ReadType, UpdateType>(this.itemRoute(itemId), payload);
}
async patchOne(itemId: string, payload: Partial<UpdateType>) {
return await this.requests.patch<ReadType, Partial<UpdateType>>(this.itemRoute(itemId), payload);
}
async deleteOne(itemId: string | number) {
return await this.requests.delete<ReadType>(this.itemRoute(itemId));
}
async duplicateOne(itemId: string | number, newName: string | undefined) {
return await this.requests.post<Recipe>(`${this.itemRoute(itemId)}/duplicate`, {
name: newName,
});
}
}

View File

@@ -1 +0,0 @@
export { route } from "./route";

View File

@@ -1,38 +0,0 @@
const parts = {
host: "http://localhost.com",
prefix: "",
};
export function overrideParts(host: string, prefix: string) {
parts.host = host;
parts.prefix = prefix;
}
export type QueryValue = string | string[] | number | number[] | boolean | null | undefined;
/**
* route is a the main URL builder for the API. It will use a predefined host and prefix (global)
* in the urls.ts file and then append the passed in path parameter uring the `URL` class from the
* browser. It will also append any query parameters passed in as the second parameter.
*
* The default host `http://localhost.com` is removed from the path if it is present. This allows us
* to bootstrap the API with different hosts as needed (like for testing) but still allows us to use
* relative URLs in production because the API and client bundle are served from the same server/host.
*/
export function route(rest: string, params: Record<string, QueryValue> | null = null): string {
const url = new URL(parts.prefix + rest, parts.host);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (Array.isArray(value)) {
for (const item of value) {
url.searchParams.append(key, String(item));
}
}
else {
url.searchParams.append(key, String(value));
}
}
}
return url.toString().replace("http://localhost.com", "");
}

View File

@@ -1,24 +0,0 @@
import { describe, expect, it } from "vitest";
import { route } from ".";
describe("UrlBuilder", () => {
it("basic query parameter", () => {
const result = route("/test", { a: "b" });
expect(result).toBe("/test?a=b");
});
it("multiple query parameters", () => {
const result = route("/test", { a: "b", c: "d" });
expect(result).toBe("/test?a=b&c=d");
});
it("no query parameters", () => {
const result = route("/test");
expect(result).toBe("/test");
});
it("list-like query parameters", () => {
const result = route("/test", { a: ["b", "c"] });
expect(result).toBe("/test?a=b&a=c");
});
});

View File

@@ -1,33 +0,0 @@
import { AdminAboutAPI } from "./admin/admin-about";
import { AdminUsersApi } from "./admin/admin-users";
import { AdminHouseholdsApi } from "./admin/admin-households";
import { AdminGroupsApi } from "./admin/admin-groups";
import { AdminBackupsApi } from "./admin/admin-backups";
import { AdminMaintenanceApi } from "./admin/admin-maintenance";
import { AdminAnalyticsApi } from "./admin/admin-analytics";
import { AdminDebugAPI } from "./admin/admin-debug";
import type { ApiRequestInstance } from "~/lib/api/types/non-generated";
export class AdminAPI {
public about: AdminAboutAPI;
public users: AdminUsersApi;
public households: AdminHouseholdsApi;
public groups: AdminGroupsApi;
public backups: AdminBackupsApi;
public maintenance: AdminMaintenanceApi;
public analytics: AdminAnalyticsApi;
public debug: AdminDebugAPI;
constructor(requests: ApiRequestInstance) {
this.about = new AdminAboutAPI(requests);
this.users = new AdminUsersApi(requests);
this.households = new AdminHouseholdsApi(requests);
this.groups = new AdminGroupsApi(requests);
this.backups = new AdminBackupsApi(requests);
this.maintenance = new AdminMaintenanceApi(requests);
this.analytics = new AdminAnalyticsApi(requests);
this.debug = new AdminDebugAPI(requests);
Object.freeze(this);
}
}

View File

@@ -1,25 +0,0 @@
import { ValidatorsApi } from "./public/validators";
import { ExploreApi } from "./public/explore";
import { SharedApi } from "./public/shared";
import type { ApiRequestInstance } from "~/lib/api/types/non-generated";
export class PublicApi {
public validators: ValidatorsApi;
public shared: SharedApi;
constructor(requests: ApiRequestInstance) {
this.validators = new ValidatorsApi(requests);
this.shared = new SharedApi(requests);
}
}
export class PublicExploreApi extends PublicApi {
public explore: ExploreApi;
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(requests);
this.explore = new ExploreApi(requests, groupSlug);
Object.freeze(this);
}
}

View File

@@ -1,97 +0,0 @@
import { RecipeAPI } from "./user/recipes";
import { UserApi } from "./user/users";
import { HouseholdAPI } from "./user/households";
import { GroupAPI } from "./user/groups";
import { BackupAPI } from "./user/backups";
import { UploadFile } from "./user/upload";
import { CategoriesAPI } from "./user/organizer-categories";
import { TagsAPI } from "./user/organizer-tags";
import { UtilsAPI } from "./user/utils";
import { FoodAPI } from "./user/recipe-foods";
import { UnitAPI } from "./user/recipe-units";
import { CookbookAPI } from "./user/group-cookbooks";
import { GroupRecipeActionsAPI } from "./user/group-recipe-actions";
import { WebhooksAPI } from "./user/group-webhooks";
import { RegisterAPI } from "./user/user-registration";
import { MealPlanAPI } from "./user/group-mealplan";
import { EmailAPI } from "./user/email";
import { BulkActionsAPI } from "./user/recipe-bulk-actions";
import { ToolsApi } from "./user/organizer-tools";
import { GroupMigrationApi } from "./user/group-migrations";
import { GroupReportsApi } from "./user/group-reports";
import { ShoppingApi } from "./user/group-shopping-lists";
import { MultiPurposeLabelsApi } from "./user/group-multiple-purpose-labels";
import { GroupEventNotifierApi } from "./user/group-event-notifier";
import { MealPlanRulesApi } from "./user/group-mealplan-rules";
import { GroupDataSeederApi } from "./user/group-seeder";
import type { ApiRequestInstance } from "~/lib/api/types/non-generated";
export class UserApiClient {
public recipes: RecipeAPI;
public users: UserApi;
public households: HouseholdAPI;
public groups: GroupAPI;
public backups: BackupAPI;
public categories: CategoriesAPI;
public tags: TagsAPI;
public utils: UtilsAPI;
public foods: FoodAPI;
public units: UnitAPI;
public cookbooks: CookbookAPI;
public groupRecipeActions: GroupRecipeActionsAPI;
public groupWebhooks: WebhooksAPI;
public register: RegisterAPI;
public mealplans: MealPlanAPI;
public mealplanRules: MealPlanRulesApi;
public email: EmailAPI;
public bulk: BulkActionsAPI;
public groupMigration: GroupMigrationApi;
public groupReports: GroupReportsApi;
public tools: ToolsApi;
public shopping: ShoppingApi;
public multiPurposeLabels: MultiPurposeLabelsApi;
public groupEventNotifier: GroupEventNotifierApi;
public upload: UploadFile;
public seeders: GroupDataSeederApi;
constructor(requests: ApiRequestInstance) {
// Recipes
this.recipes = new RecipeAPI(requests);
this.categories = new CategoriesAPI(requests);
this.tags = new TagsAPI(requests);
this.units = new UnitAPI(requests);
this.foods = new FoodAPI(requests);
this.tools = new ToolsApi(requests);
// Users
this.users = new UserApi(requests);
this.households = new HouseholdAPI(requests);
this.groups = new GroupAPI(requests);
this.cookbooks = new CookbookAPI(requests);
this.groupRecipeActions = new GroupRecipeActionsAPI(requests);
this.groupWebhooks = new WebhooksAPI(requests);
this.register = new RegisterAPI(requests);
this.mealplans = new MealPlanAPI(requests);
this.mealplanRules = new MealPlanRulesApi(requests);
// Group
this.groupMigration = new GroupMigrationApi(requests);
this.groupReports = new GroupReportsApi(requests);
this.shopping = new ShoppingApi(requests);
this.multiPurposeLabels = new MultiPurposeLabelsApi(requests);
this.seeders = new GroupDataSeederApi(requests);
// Admin
this.backups = new BackupAPI(requests);
// Utils
this.upload = new UploadFile(requests);
this.utils = new UtilsAPI(requests);
this.email = new EmailAPI(requests);
this.bulk = new BulkActionsAPI(requests);
this.groupEventNotifier = new GroupEventNotifierApi(requests);
Object.freeze(this);
}
}

View File

@@ -1,5 +0,0 @@
const PREFIX = "/api";
export const config = {
PREFIX,
};

View File

@@ -1,3 +0,0 @@
export { AdminAPI } from "./client-admin";
export { PublicApi } from "./client-public";
export { UserApiClient as UserApi } from "./client-user";

View File

@@ -1,28 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
import { PublicRecipeApi } from "./explore/recipes";
import { PublicFoodsApi } from "./explore/foods";
import { PublicCategoriesApi, PublicTagsApi, PublicToolsApi } from "./explore/organizers";
import { PublicCookbooksApi } from "./explore/cookbooks";
import { PublicHouseholdApi } from "./explore/households";
export class ExploreApi extends BaseAPI {
public recipes: PublicRecipeApi;
public cookbooks: PublicCookbooksApi;
public foods: PublicFoodsApi;
public categories: PublicCategoriesApi;
public tags: PublicTagsApi;
public tools: PublicToolsApi;
public households: PublicHouseholdApi
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(requests);
this.recipes = new PublicRecipeApi(requests, groupSlug);
this.cookbooks = new PublicCookbooksApi(requests, groupSlug);
this.foods = new PublicFoodsApi(requests, groupSlug);
this.categories = new PublicCategoriesApi(requests, groupSlug);
this.tags = new PublicTagsApi(requests, groupSlug);
this.tools = new PublicToolsApi(requests, groupSlug);
this.households = new PublicHouseholdApi(requests, groupSlug);
}
}

View File

@@ -1,21 +0,0 @@
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
import { ReadCookBook } from "~/lib/api/types/cookbook";
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
const prefix = "/api";
const exploreGroupSlug = (groupSlug: string | number) => `${prefix}/explore/groups/${groupSlug}`
const routes = {
cookbooksGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/cookbooks`,
cookbooksGroupSlugCookbookId: (groupSlug: string | number, cookbookId: string | number) => `${exploreGroupSlug(groupSlug)}/cookbooks/${cookbookId}`,
};
export class PublicCookbooksApi extends BaseCRUDAPIReadOnly<ReadCookBook> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.cookbooksGroupSlug(groupSlug),
(itemId: string | number) => routes.cookbooksGroupSlugCookbookId(groupSlug, itemId)
);
}
}

View File

@@ -1,21 +0,0 @@
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
import { IngredientFood } from "~/lib/api/types/recipe";
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
const prefix = "/api";
const exploreGroupSlug = (groupSlug: string | number) => `${prefix}/explore/groups/${groupSlug}`
const routes = {
foodsGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/foods`,
foodsGroupSlugFoodId: (groupSlug: string | number, foodId: string | number) => `${exploreGroupSlug(groupSlug)}/foods/${foodId}`,
};
export class PublicFoodsApi extends BaseCRUDAPIReadOnly<IngredientFood> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.foodsGroupSlug(groupSlug),
(itemId: string | number) => routes.foodsGroupSlugFoodId(groupSlug, itemId)
);
}
}

View File

@@ -1,21 +0,0 @@
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
import { HouseholdSummary } from "~/lib/api/types/household";
import { ApiRequestInstance, PaginationData } from "~/lib/api/types/non-generated";
const prefix = "/api";
const exploreGroupSlug = (groupSlug: string | number) => `${prefix}/explore/groups/${groupSlug}`
const routes = {
householdsGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/households`,
householdsGroupSlugHouseholdSlug: (groupSlug: string | number, householdSlug: string | number) => `${exploreGroupSlug(groupSlug)}/households/${householdSlug}`,
};
export class PublicHouseholdApi extends BaseCRUDAPIReadOnly<HouseholdSummary> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.householdsGroupSlug(groupSlug),
(itemId: string | number) => routes.householdsGroupSlugHouseholdSlug(groupSlug, itemId)
);
}
}

View File

@@ -1,45 +0,0 @@
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
import { RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/recipe";
import { ApiRequestInstance } from "~/lib/api/types/non-generated";
const prefix = "/api";
const exploreGroupSlug = (groupSlug: string | number) => `${prefix}/explore/groups/${groupSlug}`
const routes = {
categoriesGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/categories`,
categoriesGroupSlugCategoryId: (groupSlug: string | number, categoryId: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/categories/${categoryId}`,
tagsGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/tags`,
tagsGroupSlugTagId: (groupSlug: string | number, tagId: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/tags/${tagId}`,
toolsGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/tools`,
toolsGroupSlugToolId: (groupSlug: string | number, toolId: string | number) => `${exploreGroupSlug(groupSlug)}/organizers/tools`,
};
export class PublicCategoriesApi extends BaseCRUDAPIReadOnly<RecipeCategory> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.categoriesGroupSlug(groupSlug),
(itemId: string | number) => routes.categoriesGroupSlugCategoryId(groupSlug, itemId)
);
}
}
export class PublicTagsApi extends BaseCRUDAPIReadOnly<RecipeTag> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.tagsGroupSlug(groupSlug),
(itemId: string | number) => routes.tagsGroupSlugTagId(groupSlug, itemId)
);
}
}
export class PublicToolsApi extends BaseCRUDAPIReadOnly<RecipeTool> {
constructor(requests: ApiRequestInstance, groupSlug: string) {
super(
requests,
routes.toolsGroupSlug(groupSlug),
(itemId: string | number) => routes.toolsGroupSlugToolId(groupSlug, itemId)
);
}
}

View File

@@ -1,33 +0,0 @@
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
import { route } from "../../base";
import { Recipe, RecipeSuggestionQuery, RecipeSuggestionResponse } from "~/lib/api/types/recipe";
import { ApiRequestInstance, PaginationData } from "~/lib/api/types/non-generated";
import { RecipeSearchQuery } from "../../user/recipes/recipe";
const prefix = "/api";
const exploreGroupSlug = (groupSlug: string | number) => `${prefix}/explore/groups/${groupSlug}`
const routes = {
recipesGroupSlug: (groupSlug: string | number) => `${exploreGroupSlug(groupSlug)}/recipes`,
recipesGroupSlugRecipeSlug: (groupSlug: string | number, recipeSlug: string | number) => `${exploreGroupSlug(groupSlug)}/recipes/${recipeSlug}`,
};
export class PublicRecipeApi extends BaseCRUDAPIReadOnly<Recipe> {
constructor(requests: ApiRequestInstance, private readonly groupSlug: string) {
super(
requests,
routes.recipesGroupSlug(groupSlug),
(itemId: string | number) => routes.recipesGroupSlugRecipeSlug(groupSlug, itemId)
);
}
async search(rsq: RecipeSearchQuery) {
return await this.requests.get<PaginationData<Recipe>>(route(routes.recipesGroupSlug(this.groupSlug), rsq));
}
async getSuggestions(q: RecipeSuggestionQuery, foods: string[] | null = null, tools: string[]| null = null) {
return await this.requests.get<RecipeSuggestionResponse>(
route(`${routes.recipesGroupSlug(this.groupSlug)}/suggestions`, { ...q, foods, tools })
);
}
}

View File

@@ -1,14 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import { Recipe } from "~/lib/api/types/recipe";
const prefix = "/api";
const routes = {
recipeShareToken: (token: string) => `${prefix}/recipes/shared/${token}`,
};
export class SharedApi extends BaseAPI {
async getShared(item_id: string) {
return await this.requests.get<Recipe>(routes.recipeShareToken(item_id));
}
}

View File

@@ -1,29 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import { ValidationResponse } from "~/lib/api/types/response";
const prefix = "/api";
const routes = {
group: (name: string) => `${prefix}/validators/group?name=${name}`,
user: (name: string) => `${prefix}/validators/user/name?name=${name}`,
email: (name: string) => `${prefix}/validators/user/email?email=${name}`,
recipe: (groupId: string, name: string) => `${prefix}/validators/group/recipe?group_id=${groupId}?name=${name}`,
};
export class ValidatorsApi extends BaseAPI {
async group(name: string) {
return await this.requests.get<ValidationResponse>(routes.group(name));
}
async username(name: string) {
return await this.requests.get<ValidationResponse>(routes.user(name));
}
async email(email: string) {
return await this.requests.get<ValidationResponse>(routes.email(email));
}
async recipe(groupId: string, name: string) {
return await this.requests.get<ValidationResponse>(routes.recipe(groupId, name));
}
}

View File

@@ -1,18 +0,0 @@
export type I18n = ReturnType<typeof useI18n>;
export type TRoute = string;
export type TranslationResult = string;
export type ActivityRoute = (groupSlug?: string) => TRoute;
export type ActivityLabel = (i18n: I18n) => TranslationResult;
export type Activity = {
key: ActivityKey;
route: ActivityRoute;
label: ActivityLabel;
};
export const enum ActivityKey {
RECIPES = "recipes",
MEALPLANNER = "mealplanner",
SHOPPING_LIST = "shopping_list",
}

View File

@@ -1,194 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export interface AdminAboutInfo {
production: boolean;
version: string;
demoStatus: boolean;
allowSignup: boolean;
allowPasswordLogin: boolean;
defaultGroupSlug?: string | null;
defaultHouseholdSlug?: string | null;
enableOidc: boolean;
oidcRedirect: boolean;
oidcProviderName: string;
enableOpenai: boolean;
enableOpenaiImageServices: boolean;
enableOpenaiTranscriptionServices: boolean;
tokenTime: number;
versionLatest: string;
apiPort: number;
apiDocs: boolean;
dbType: string;
dbUrl?: string | null;
defaultGroup: string;
defaultHousehold: string;
buildId: string;
recipeScraperVersion: string;
}
export interface AllBackups {
imports: BackupFile[];
templates: string[];
}
export interface BackupFile {
name: string;
date: string;
size: string;
}
export interface AppInfo {
production: boolean;
version: string;
demoStatus: boolean;
allowSignup: boolean;
allowPasswordLogin: boolean;
defaultGroupSlug?: string | null;
defaultHouseholdSlug?: string | null;
enableOidc: boolean;
oidcRedirect: boolean;
oidcProviderName: string;
enableOpenai: boolean;
enableOpenaiImageServices: boolean;
enableOpenaiTranscriptionServices: boolean;
tokenTime: number;
}
export interface AppStartupInfo {
isFirstLogin: boolean;
isDemo: boolean;
}
export interface AppStatistics {
totalRecipes: number;
totalUsers: number;
totalHouseholds: number;
totalGroups: number;
uncategorizedRecipes: number;
untaggedRecipes: number;
}
export interface AppTheme {
lightPrimary?: string;
lightAccent?: string;
lightSecondary?: string;
lightSuccess?: string;
lightInfo?: string;
lightWarning?: string;
lightError?: string;
darkPrimary?: string;
darkAccent?: string;
darkSecondary?: string;
darkSuccess?: string;
darkInfo?: string;
darkWarning?: string;
darkError?: string;
}
export interface BackupOptions {
recipes?: boolean;
settings?: boolean;
themes?: boolean;
groups?: boolean;
users?: boolean;
notifications?: boolean;
}
export interface CheckAppConfig {
emailReady: boolean;
ldapReady: boolean;
oidcReady: boolean;
enableOpenai: boolean;
baseUrlSet: boolean;
isUpToDate: boolean;
}
export interface ChowdownURL {
url: string;
}
export interface CommentImport {
name: string;
status: boolean;
exception?: string | null;
}
export interface CreateBackup {
tag?: string | null;
options: BackupOptions;
templates?: string[] | null;
}
export interface DebugResponse {
success: boolean;
response?: string | null;
}
export interface EmailReady {
ready: boolean;
}
export interface EmailSuccess {
success: boolean;
error?: string | null;
}
export interface EmailTest {
email: string;
}
export interface GroupImport {
name: string;
status: boolean;
exception?: string | null;
}
export interface ImportBase {
name: string;
status: boolean;
exception?: string | null;
}
export interface ImportJob {
recipes?: boolean;
settings?: boolean;
themes?: boolean;
groups?: boolean;
users?: boolean;
notifications?: boolean;
name: string;
force?: boolean;
rebase?: boolean;
}
export interface MaintenanceLogs {
logs: string[];
}
export interface MaintenanceStorageDetails {
tempDirSize: string;
backupsDirSize: string;
groupsDirSize: string;
recipesDirSize: string;
userDirSize: string;
}
export interface MaintenanceSummary {
dataDirSize: string;
cleanableImages: number;
cleanableDirs: number;
}
export interface MigrationFile {
name: string;
date: string;
}
export interface MigrationImport {
name: string;
status: boolean;
exception?: string | null;
slug?: string | null;
}
export interface Migrations {
type: string;
files?: MigrationFile[];
}
export interface RecipeImport {
name: string;
status: boolean;
exception?: string | null;
slug?: string | null;
}
export interface SettingsImport {
name: string;
status: boolean;
exception?: string | null;
}
export interface UserImport {
name: string;
status: boolean;
exception?: string | null;
}

View File

@@ -1,20 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export interface MealieAnalytics {
installationId: string;
version: string;
databaseType: string;
usingEmail: boolean;
usingLdap: boolean;
apiTokens: number;
users: number;
groups: number;
recipes: number;
shoppingLists: number;
cookbooks: number;
}

View File

@@ -1,69 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type LogicalOperator = "AND" | "OR";
export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE";
export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<=";
export interface CookbookHousehold {
id: string;
name: string;
}
export interface CreateCookBook {
name: string;
description?: string;
slug?: string | null;
position?: number;
public?: boolean;
queryFilterString?: string;
}
export interface ReadCookBook {
name: string;
description?: string;
slug?: string | null;
position?: number;
public?: boolean;
queryFilterString?: string;
groupId: string;
householdId: string;
id: string;
queryFilter?: QueryFilterJSON;
household?: CookbookHousehold | null;
}
export interface QueryFilterJSON {
parts?: QueryFilterJSONPart[];
}
export interface QueryFilterJSONPart {
leftParenthesis?: string | null;
rightParenthesis?: string | null;
logicalOperator?: LogicalOperator | null;
attributeName?: string | null;
relationalOperator?: RelationalKeyword | RelationalOperator | null;
value?: string | string[] | null;
[k: string]: unknown;
}
export interface SaveCookBook {
name: string;
description?: string;
slug?: string | null;
position?: number;
public?: boolean;
queryFilterString?: string;
groupId: string;
householdId: string;
}
export interface UpdateCookBook {
name: string;
description?: string;
slug?: string | null;
position?: number;
public?: boolean;
queryFilterString?: string;
groupId: string;
householdId: string;
id: string;
}

View File

@@ -1,24 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type EventCategory = "general" | "recipe" | "backup" | "scheduled" | "migration" | "group" | "user";
export interface Event {
id?: number;
title: string;
text: string;
timeStamp?: string;
category?: EventCategory & string;
}
export interface EventsOut {
total: number;
events: Event[];
}
export interface TestEvent {
id?: number;
testUrl?: string;
}

View File

@@ -1,57 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* 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
*/
export type SupportedMigrations =
| "nextcloud"
| "chowdown"
| "copymethat"
| "paprika"
| "mealie_alpha"
| "tandoor"
| "plantoeat"
| "myrecipebox"
| "recipekeeper"
| "cookn";
export interface CreateGroupPreferences {
privateGroup?: boolean;
groupId: string;
}
export interface DataMigrationCreate {
sourceType: SupportedMigrations;
}
export interface GroupAdminUpdate {
id: string;
name: string;
preferences?: UpdateGroupPreferences | null;
}
export interface UpdateGroupPreferences {
privateGroup?: boolean;
}
export interface GroupDataExport {
id: string;
groupId: string;
name: string;
filename: string;
path: string;
size: string;
expires: string;
}
export interface GroupStorage {
usedStorageBytes: number;
usedStorageStr: string;
totalStorageBytes: number;
totalStorageStr: string;
}
export interface ReadGroupPreferences {
privateGroup?: boolean;
groupId: string;
id: string;
}
export interface SeederConfig {
locale: string;
}

View File

@@ -1,787 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type GroupRecipeActionType = "link" | "post";
export type WebhookType = "mealplan";
export interface CreateGroupRecipeAction {
actionType: GroupRecipeActionType;
title: string;
url: string;
}
export interface CreateHouseholdPreferences {
privateHousehold?: boolean;
lockRecipeEditsFromOtherHouseholds?: boolean;
firstDayOfWeek?: number;
recipePublic?: boolean;
recipeShowNutrition?: boolean;
recipeShowAssets?: boolean;
recipeLandscapeView?: boolean;
recipeDisableComments?: boolean;
}
export interface CreateInviteToken {
uses: number;
groupId?: string | null;
householdId?: string | null;
}
export interface CreateWebhook {
enabled?: boolean;
name?: string;
url?: string;
webhookType?: WebhookType;
scheduledTime: string;
}
export interface EmailInitationResponse {
success: boolean;
error?: string | null;
}
export interface EmailInvitation {
email: string;
token: string;
}
export interface GroupEventNotifierCreate {
name: string;
appriseUrl?: string | null;
}
export interface GroupEventNotifierOptions {
testMessage?: boolean;
webhookTask?: boolean;
recipeCreated?: boolean;
recipeUpdated?: boolean;
recipeDeleted?: boolean;
userSignup?: boolean;
dataMigrations?: boolean;
dataExport?: boolean;
dataImport?: boolean;
mealplanEntryCreated?: boolean;
mealplanEntryUpdated?: boolean;
mealplanEntryDeleted?: boolean;
shoppingListCreated?: boolean;
shoppingListUpdated?: boolean;
shoppingListDeleted?: boolean;
cookbookCreated?: boolean;
cookbookUpdated?: boolean;
cookbookDeleted?: boolean;
tagCreated?: boolean;
tagUpdated?: boolean;
tagDeleted?: boolean;
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
}
export interface GroupEventNotifierOptionsOut {
testMessage?: boolean;
webhookTask?: boolean;
recipeCreated?: boolean;
recipeUpdated?: boolean;
recipeDeleted?: boolean;
userSignup?: boolean;
dataMigrations?: boolean;
dataExport?: boolean;
dataImport?: boolean;
mealplanEntryCreated?: boolean;
mealplanEntryUpdated?: boolean;
mealplanEntryDeleted?: boolean;
shoppingListCreated?: boolean;
shoppingListUpdated?: boolean;
shoppingListDeleted?: boolean;
cookbookCreated?: boolean;
cookbookUpdated?: boolean;
cookbookDeleted?: boolean;
tagCreated?: boolean;
tagUpdated?: boolean;
tagDeleted?: boolean;
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
id: string;
}
export interface GroupEventNotifierOptionsSave {
testMessage?: boolean;
webhookTask?: boolean;
recipeCreated?: boolean;
recipeUpdated?: boolean;
recipeDeleted?: boolean;
userSignup?: boolean;
dataMigrations?: boolean;
dataExport?: boolean;
dataImport?: boolean;
mealplanEntryCreated?: boolean;
mealplanEntryUpdated?: boolean;
mealplanEntryDeleted?: boolean;
shoppingListCreated?: boolean;
shoppingListUpdated?: boolean;
shoppingListDeleted?: boolean;
cookbookCreated?: boolean;
cookbookUpdated?: boolean;
cookbookDeleted?: boolean;
tagCreated?: boolean;
tagUpdated?: boolean;
tagDeleted?: boolean;
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
notifierId: string;
}
export interface GroupEventNotifierOut {
id: string;
name: string;
enabled: boolean;
groupId: string;
householdId: string;
options: GroupEventNotifierOptionsOut;
}
export interface GroupEventNotifierPrivate {
id: string;
name: string;
enabled: boolean;
groupId: string;
householdId: string;
options: GroupEventNotifierOptionsOut;
appriseUrl: string;
}
export interface GroupEventNotifierSave {
name: string;
appriseUrl?: string | null;
enabled?: boolean;
groupId: string;
householdId: string;
options?: GroupEventNotifierOptions;
}
export interface GroupEventNotifierUpdate {
name: string;
appriseUrl?: string | null;
enabled?: boolean;
groupId: string;
householdId: string;
options?: GroupEventNotifierOptions;
id: string;
}
export interface GroupRecipeActionOut {
actionType: GroupRecipeActionType;
title: string;
url: string;
groupId: string;
householdId: string;
id: string;
}
export interface GroupRecipeActionPayload {
action: GroupRecipeActionOut;
content: unknown;
recipeScale: number;
}
export interface HouseholdCreate {
groupId?: string | null;
name: string;
}
export interface HouseholdInDB {
groupId: string;
name: string;
id: string;
slug: string;
preferences?: ReadHouseholdPreferences | null;
group: string;
users?: HouseholdUserSummary[] | null;
webhooks?: ReadWebhook[];
}
export interface ReadHouseholdPreferences {
privateHousehold?: boolean;
lockRecipeEditsFromOtherHouseholds?: boolean;
firstDayOfWeek?: number;
recipePublic?: boolean;
recipeShowNutrition?: boolean;
recipeShowAssets?: boolean;
recipeLandscapeView?: boolean;
recipeDisableComments?: boolean;
id: string;
}
export interface HouseholdUserSummary {
id: string;
fullName: string;
}
export interface ReadWebhook {
enabled?: boolean;
name?: string;
url?: string;
webhookType?: WebhookType;
scheduledTime: string;
groupId: string;
householdId: string;
id: string;
}
export interface HouseholdRecipeBase {
lastMade?: string | null;
}
export interface HouseholdRecipeCreate {
lastMade?: string | null;
householdId: string;
recipeId: string;
}
export interface HouseholdRecipeOut {
lastMade?: string | null;
householdId: string;
recipeId: string;
id: string;
}
export interface HouseholdRecipeSummary {
lastMade?: string | null;
recipeId: string;
}
export interface HouseholdRecipeUpdate {
lastMade?: string | null;
}
export interface HouseholdSave {
groupId: string;
name: string;
}
export interface HouseholdStatistics {
totalRecipes: number;
totalUsers: number;
totalCategories: number;
totalTags: number;
totalTools: number;
}
export interface HouseholdSummary {
groupId: string;
name: string;
id: string;
slug: string;
preferences?: ReadHouseholdPreferences | null;
}
export interface ReadInviteToken {
token: string;
usesLeft: number;
groupId: string;
householdId: string;
}
export interface SaveGroupRecipeAction {
actionType: GroupRecipeActionType;
title: string;
url: string;
groupId: string;
householdId: string;
}
export interface SaveHouseholdPreferences {
privateHousehold?: boolean;
lockRecipeEditsFromOtherHouseholds?: boolean;
firstDayOfWeek?: number;
recipePublic?: boolean;
recipeShowNutrition?: boolean;
recipeShowAssets?: boolean;
recipeLandscapeView?: boolean;
recipeDisableComments?: boolean;
householdId: string;
}
export interface SaveInviteToken {
usesLeft: number;
groupId: string;
householdId: string;
token: string;
}
export interface SaveWebhook {
enabled?: boolean;
name?: string;
url?: string;
webhookType?: WebhookType;
scheduledTime: string;
groupId: string;
householdId: string;
}
export interface SetPermissions {
userId: string;
canManageHousehold?: boolean;
canManage?: boolean;
canInvite?: boolean;
canOrganize?: boolean;
}
export interface ShoppingListAddRecipeParams {
recipeIncrementQuantity?: number;
recipeIngredients?: RecipeIngredient[] | null;
}
export interface RecipeIngredient {
quantity?: number | null;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
title?: string | null;
originalText?: string | null;
referenceId?: string;
}
export interface IngredientUnit {
id: string;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
fraction?: boolean;
abbreviation?: string;
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: IngredientUnitAlias[];
standardQuantity?: number | null;
standardUnit?: string | null;
createdAt?: string | null;
updatedAt?: string | null;
}
export interface IngredientUnitAlias {
name: string;
}
export interface CreateIngredientUnit {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
fraction?: boolean;
abbreviation?: string;
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: CreateIngredientUnitAlias[];
standardQuantity?: number | null;
standardUnit?: string | null;
}
export interface CreateIngredientUnitAlias {
name: string;
}
export interface IngredientFood {
id: string;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
labelId?: string | null;
aliases?: IngredientFoodAlias[];
householdsWithIngredientFood?: string[];
label?: MultiPurposeLabelSummary | null;
createdAt?: string | null;
updatedAt?: string | null;
}
export interface IngredientFoodAlias {
name: string;
}
export interface MultiPurposeLabelSummary {
name: string;
color?: string;
groupId: string;
id: string;
}
export interface CreateIngredientFood {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
labelId?: string | null;
aliases?: CreateIngredientFoodAlias[];
householdsWithIngredientFood?: string[];
}
export interface CreateIngredientFoodAlias {
name: string;
}
export interface Recipe {
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;
recipeIngredient?: RecipeIngredient[];
recipeInstructions?: RecipeStep[] | null;
nutrition?: Nutrition | null;
settings?: RecipeSettings | null;
assets?: RecipeAsset[] | null;
notes?: RecipeNote[] | null;
extras?: {
[k: string]: unknown;
} | null;
comments?: RecipeCommentOut[] | null;
}
export interface RecipeCategory {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
}
export interface RecipeTag {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
}
export interface RecipeTool {
id: string;
groupId?: string | null;
name: string;
slug: string;
householdsWithTool?: string[];
}
export interface RecipeStep {
id?: string | null;
title?: string | null;
summary?: string | null;
text: string;
ingredientReferences?: IngredientReferences[];
}
export interface IngredientReferences {
referenceId?: string | null;
}
export interface Nutrition {
calories?: string | null;
carbohydrateContent?: string | null;
cholesterolContent?: string | null;
fatContent?: string | null;
fiberContent?: string | null;
proteinContent?: string | null;
saturatedFatContent?: string | null;
sodiumContent?: string | null;
sugarContent?: string | null;
transFatContent?: string | null;
unsaturatedFatContent?: string | null;
}
export interface RecipeSettings {
public?: boolean;
showNutrition?: boolean;
showAssets?: boolean;
landscapeView?: boolean;
disableComments?: boolean;
locked?: boolean;
}
export interface RecipeAsset {
name: string;
icon: string;
fileName?: string | null;
}
export interface RecipeNote {
title: string;
text: string;
}
export interface RecipeCommentOut {
recipeId: string;
text: string;
id: string;
createdAt: string;
updatedAt: string;
userId: string;
user: UserBase;
}
export interface UserBase {
id: string;
username?: string | null;
admin: boolean;
fullName?: string | null;
}
export interface ShoppingListAddRecipeParamsBulk {
recipeIncrementQuantity?: number;
recipeIngredients?: RecipeIngredient[] | null;
recipeId: string;
}
export interface ShoppingListCreate {
name?: string | null;
extras?: {
[k: string]: unknown;
} | null;
createdAt?: string | null;
updatedAt?: string | null;
}
export interface ShoppingListItemBase {
quantity?: number;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
shoppingListId: string;
checked?: boolean;
position?: number;
foodId?: string | null;
labelId?: string | null;
unitId?: string | null;
extras?: {
[k: string]: unknown;
} | null;
}
export interface ShoppingListItemCreate {
quantity?: number;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
shoppingListId: string;
checked?: boolean;
position?: number;
foodId?: string | null;
labelId?: string | null;
unitId?: string | null;
extras?: {
[k: string]: unknown;
} | null;
id?: string | null;
recipeReferences?: ShoppingListItemRecipeRefCreate[];
}
export interface ShoppingListItemRecipeRefCreate {
recipeId: string;
recipeQuantity?: number;
recipeScale?: number | null;
recipeNote?: string | null;
}
export interface ShoppingListItemOut {
quantity?: number;
unit?: IngredientUnit | null;
food?: IngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
shoppingListId: string;
checked?: boolean;
position?: number;
foodId?: string | null;
labelId?: string | null;
unitId?: string | null;
extras?: {
[k: string]: unknown;
} | null;
id: string;
groupId: string;
householdId: string;
label?: MultiPurposeLabelSummary | null;
recipeReferences?: ShoppingListItemRecipeRefOut[];
createdAt?: string | null;
updatedAt?: string | null;
}
export interface ShoppingListItemRecipeRefOut {
recipeId: string;
recipeQuantity?: number;
recipeScale?: number | null;
recipeNote?: string | null;
id: string;
shoppingListItemId: string;
}
export interface ShoppingListItemRecipeRefUpdate {
recipeId: string;
recipeQuantity?: number;
recipeScale?: number | null;
recipeNote?: string | null;
id: string;
shoppingListItemId: string;
}
export interface ShoppingListItemUpdate {
quantity?: number;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
shoppingListId: string;
checked?: boolean;
position?: number;
foodId?: string | null;
labelId?: string | null;
unitId?: string | null;
extras?: {
[k: string]: unknown;
} | null;
recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[];
}
export interface ShoppingListItemUpdateBulk {
quantity?: number;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
shoppingListId: string;
checked?: boolean;
position?: number;
foodId?: string | null;
labelId?: string | null;
unitId?: string | null;
extras?: {
[k: string]: unknown;
} | null;
recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[];
id: string;
}
export interface ShoppingListItemsCollectionOut {
createdItems?: ShoppingListItemOut[];
updatedItems?: ShoppingListItemOut[];
deletedItems?: ShoppingListItemOut[];
}
export interface ShoppingListMultiPurposeLabelCreate {
shoppingListId: string;
labelId: string;
position?: number;
}
export interface ShoppingListMultiPurposeLabelOut {
shoppingListId: string;
labelId: string;
position?: number;
id: string;
label: MultiPurposeLabelSummary;
}
export interface ShoppingListMultiPurposeLabelUpdate {
shoppingListId: string;
labelId: string;
position?: number;
id: string;
}
export interface ShoppingListOut {
name?: string | null;
extras?: {
[k: string]: unknown;
} | null;
createdAt?: string | null;
updatedAt?: string | null;
groupId: string;
userId: string;
id: string;
listItems?: ShoppingListItemOut[];
householdId: string;
recipeReferences?: ShoppingListRecipeRefOut[];
labelSettings?: ShoppingListMultiPurposeLabelOut[];
}
export interface ShoppingListRecipeRefOut {
id: string;
shoppingListId: string;
recipeId: string;
recipeQuantity: number;
recipe: 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 ShoppingListRemoveRecipeParams {
recipeDecrementQuantity?: number;
}
export interface ShoppingListSave {
name?: string | null;
extras?: {
[k: string]: unknown;
} | null;
createdAt?: string | null;
updatedAt?: string | null;
groupId: string;
userId: string;
}
export interface ShoppingListSummary {
name?: string | null;
extras?: {
[k: string]: unknown;
} | null;
createdAt?: string | null;
updatedAt?: string | null;
groupId: string;
userId: string;
id: string;
householdId: string;
recipeReferences: ShoppingListRecipeRefOut[];
labelSettings: ShoppingListMultiPurposeLabelOut[];
}
export interface ShoppingListUpdate {
name?: string | null;
extras?: {
[k: string]: unknown;
} | null;
createdAt?: string | null;
updatedAt?: string | null;
groupId: string;
userId: string;
id: string;
listItems?: ShoppingListItemOut[];
}
export interface UpdateHousehold {
groupId: string;
name: string;
id: string;
slug: string;
}
export interface UpdateHouseholdAdmin {
groupId: string;
name: string;
id: string;
preferences?: UpdateHouseholdPreferences | null;
}
export interface UpdateHouseholdPreferences {
privateHousehold?: boolean;
lockRecipeEditsFromOtherHouseholds?: boolean;
firstDayOfWeek?: number;
recipePublic?: boolean;
recipeShowNutrition?: boolean;
recipeShowAssets?: boolean;
recipeLandscapeView?: boolean;
recipeDisableComments?: boolean;
}
export interface RecipeIngredientBase {
quantity?: number | null;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
}

View File

@@ -1,34 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export interface MultiPurposeLabelCreate {
name: string;
color?: string;
}
export interface MultiPurposeLabelOut {
name: string;
color?: string;
groupId: string;
id: string;
}
export interface MultiPurposeLabelSave {
name: string;
color?: string;
groupId: string;
}
export interface MultiPurposeLabelSummary {
name: string;
color?: string;
groupId: string;
id: string;
}
export interface MultiPurposeLabelUpdate {
name: string;
color?: string;
groupId: string;
id: string;
}

View File

@@ -1,152 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type PlanEntryType = "breakfast" | "lunch" | "dinner" | "side" | "snack" | "drink" | "dessert";
export type PlanRulesDay = "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday" | "unset";
export type PlanRulesType = "breakfast" | "lunch" | "dinner" | "side" | "snack" | "drink" | "dessert" | "unset";
export type LogicalOperator = "AND" | "OR";
export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE";
export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<=";
export interface CreatePlanEntry {
date: string;
entryType?: PlanEntryType;
title?: string;
text?: string;
recipeId?: string | null;
}
export interface CreateRandomEntry {
date: string;
entryType?: PlanEntryType;
}
export interface ListItem {
title?: string | null;
text?: string;
quantity?: number;
checked?: boolean;
}
export interface PlanRulesCreate {
day?: PlanRulesDay;
entryType?: PlanRulesType;
queryFilterString?: string;
}
export interface PlanRulesOut {
day?: PlanRulesDay;
entryType?: PlanRulesType;
queryFilterString?: string;
groupId: string;
householdId: string;
id: string;
queryFilter?: QueryFilterJSON;
}
export interface QueryFilterJSON {
parts?: QueryFilterJSONPart[];
}
export interface QueryFilterJSONPart {
leftParenthesis?: string | null;
rightParenthesis?: string | null;
logicalOperator?: LogicalOperator | null;
attributeName?: string | null;
relationalOperator?: RelationalKeyword | RelationalOperator | null;
value?: string | string[] | null;
[k: string]: unknown;
}
export interface PlanRulesSave {
day?: PlanRulesDay;
entryType?: PlanRulesType;
queryFilterString?: string;
groupId: string;
householdId: string;
}
export interface ReadPlanEntry {
date: string;
entryType?: PlanEntryType;
title?: string;
text?: string;
recipeId?: string | null;
id: number;
groupId: string;
userId: string;
householdId: string;
recipe?: RecipeSummary | null;
}
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;
}
export interface RecipeTag {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
}
export interface RecipeTool {
id: string;
groupId?: string | null;
name: string;
slug: string;
householdsWithTool?: string[];
}
export interface SavePlanEntry {
date: string;
entryType?: PlanEntryType;
title?: string;
text?: string;
recipeId?: string | null;
groupId: string;
userId: string;
}
export interface ShoppingListIn {
name: string;
group?: string | null;
items: ListItem[];
}
export interface ShoppingListOut {
name: string;
group?: string | null;
items: ListItem[];
id: number;
}
export interface UpdatePlanEntry {
date: string;
entryType?: PlanEntryType;
title?: string;
text?: string;
recipeId?: string | null;
id: number;
groupId: string;
userId: string;
}

View File

@@ -1,76 +0,0 @@
import type { AxiosRequestConfig, AxiosResponse } from "axios";
export type NoUndefinedField<T> = { [P in keyof T]-?: NoUndefinedField<NonNullable<T[P]>> };
export interface RequestResponse<T> {
response: AxiosResponse<T> | null;
data: T | null;
error: any;
}
export interface ApiRequestInstance {
get<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<RequestResponse<T>>;
post<T>(url: string, data: unknown, config?: AxiosRequestConfig): Promise<RequestResponse<T>>;
put<T, U = T>(url: string, data: U, config?: AxiosRequestConfig): Promise<RequestResponse<T>>;
patch<T, U = Partial<T>>(url: string, data: U, config?: AxiosRequestConfig): Promise<RequestResponse<T>>;
delete<T>(url: string, config?: AxiosRequestConfig): Promise<RequestResponse<T>>;
}
export interface PaginationData<T> {
page: number;
per_page: number;
total: number;
total_pages: number;
items: T[];
}
export type RecipeOrganizer
= | "categories"
| "tags"
| "tools"
| "foods"
| "households"
| "users";
export enum Organizer {
Category = "categories",
Tag = "tags",
Tool = "tools",
Food = "foods",
Household = "households",
User = "users",
}
export enum SSEDataEventStatus {
Progress = "progress",
Done = "done",
Error = "error",
}
export type PlaceholderKeyword = "$NOW";
export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE";
export type LogicalOperator = "AND" | "OR";
export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<=";
export interface QueryFilterJSON {
parts?: QueryFilterJSONPart[];
}
export interface QueryFilterJSONPart {
leftParenthesis?: string | null;
rightParenthesis?: string | null;
logicalOperator?: LogicalOperator | null;
attributeName?: string | null;
relationalOperator?: RelationalKeyword | RelationalOperator | null;
value?: string | string[] | null;
}
export type StandardizedUnitType
= | "fluid_ounce"
| "cup"
| "ounce"
| "pound"
| "milliliter"
| "liter"
| "gram"
| "kilogram";

View File

@@ -1,43 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* 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
*/
export interface OpenAIIngredient {
quantity?: number | null;
unit?: string | null;
food?: string | null;
note?: string | null;
}
export interface OpenAIIngredients {
ingredients?: OpenAIIngredient[];
}
export interface OpenAIRecipe {
name: string;
description?: string | null;
recipe_yield?: string | null;
total_time?: string | null;
prep_time?: string | null;
perform_time?: string | null;
ingredients?: OpenAIRecipeIngredient[];
instructions?: OpenAIRecipeInstruction[];
notes?: OpenAIRecipeNotes[];
}
export interface OpenAIRecipeIngredient {
title?: string | null;
text: string;
}
export interface OpenAIRecipeInstruction {
title?: string | null;
text: string;
}
export interface OpenAIRecipeNotes {
title?: string | null;
text: string;
}
export interface OpenAIText {
text: string;
}
export interface OpenAIBase {}

View File

@@ -1,560 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* 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
*/
export type ExportTypes = "json";
export type RegisteredParser = "nlp" | "brute" | "openai";
export type OrderByNullPosition = "first" | "last";
export type OrderDirection = "asc" | "desc";
export type TimelineEventType = "system" | "info" | "comment";
export type TimelineEventImage = "has image" | "does not have image";
export interface AssignCategories {
recipes: string[];
categories: CategoryBase[];
}
export interface CategoryBase {
name: string;
id: string;
groupId?: string | null;
slug: string;
}
export interface AssignSettings {
recipes: string[];
settings: RecipeSettings;
}
export interface RecipeSettings {
public?: boolean;
showNutrition?: boolean;
showAssets?: boolean;
landscapeView?: boolean;
disableComments?: boolean;
locked?: boolean;
}
export interface AssignTags {
recipes: string[];
tags: TagBase[];
}
export interface TagBase {
name: string;
id: string;
groupId?: string | null;
slug: string;
}
export interface CategoryIn {
name: string;
}
export interface CategoryOut {
name: string;
id: string;
groupId: string;
slug: string;
}
export interface CategorySave {
name: string;
groupId: string;
}
export interface CreateIngredientFood {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
labelId?: string | null;
aliases?: CreateIngredientFoodAlias[];
householdsWithIngredientFood?: string[];
}
export interface CreateIngredientFoodAlias {
name: string;
}
export interface CreateIngredientUnit {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
fraction?: boolean;
abbreviation?: string;
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: CreateIngredientUnitAlias[];
standardQuantity?: number | null;
standardUnit?: string | null;
}
export interface CreateIngredientUnitAlias {
name: string;
}
export interface CreateRecipe {
name: string;
}
export interface CreateRecipeBulk {
url: string;
categories?: RecipeCategory[] | null;
tags?: RecipeTag[] | null;
}
export interface RecipeCategory {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
}
export interface RecipeTag {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
}
export interface CreateRecipeByUrlBulk {
imports: CreateRecipeBulk[];
}
export interface DeleteRecipes {
recipes: string[];
}
export interface ExportBase {
recipes: string[];
}
export interface ExportRecipes {
recipes: string[];
exportType?: ExportTypes;
}
export interface IngredientConfidence {
average?: number | null;
comment?: number | null;
name?: number | null;
unit?: number | null;
quantity?: number | null;
food?: number | null;
}
export interface IngredientFood {
id: string;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
labelId?: string | null;
aliases?: IngredientFoodAlias[];
householdsWithIngredientFood?: string[];
label?: MultiPurposeLabelSummary | null;
createdAt?: string | null;
updatedAt?: string | null;
}
export interface IngredientFoodAlias {
name: string;
}
export interface MultiPurposeLabelSummary {
name: string;
color?: string;
groupId: string;
id: string;
}
export interface IngredientReferences {
referenceId?: string | null;
}
export interface IngredientRequest {
parser?: RegisteredParser;
ingredient: string;
}
export interface IngredientUnit {
id: string;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
fraction?: boolean;
abbreviation?: string;
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: IngredientUnitAlias[];
standardQuantity?: number | null;
standardUnit?: string | null;
createdAt?: string | null;
updatedAt?: string | null;
}
export interface IngredientUnitAlias {
name: string;
}
export interface IngredientsRequest {
parser?: RegisteredParser;
ingredients: string[];
}
export interface MergeFood {
fromFood: string;
toFood: string;
}
export interface MergeUnit {
fromUnit: string;
toUnit: string;
}
export interface Nutrition {
calories?: string | null;
carbohydrateContent?: string | null;
cholesterolContent?: string | null;
fatContent?: string | null;
fiberContent?: string | null;
proteinContent?: string | null;
saturatedFatContent?: string | null;
sodiumContent?: string | null;
sugarContent?: string | null;
transFatContent?: string | null;
unsaturatedFatContent?: string | null;
}
export interface ParsedIngredient {
input?: string | null;
confidence?: IngredientConfidence;
ingredient: RecipeIngredient;
}
export interface RecipeIngredient {
quantity?: number | null;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
title?: string | null;
originalText?: string | null;
referenceId?: string;
}
export interface Recipe {
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;
recipeIngredient?: RecipeIngredient[];
recipeInstructions?: RecipeStep[] | null;
nutrition?: Nutrition | null;
settings?: RecipeSettings | null;
assets?: RecipeAsset[] | null;
notes?: RecipeNote[] | null;
extras?: {
[k: string]: unknown;
} | null;
comments?: RecipeCommentOut[] | null;
}
export interface RecipeTool {
id: string;
groupId?: string | null;
name: string;
slug: string;
householdsWithTool?: string[];
}
export interface RecipeStep {
id?: string | null;
title?: string | null;
summary?: string | null;
text: string;
ingredientReferences?: IngredientReferences[];
}
export interface RecipeAsset {
name: string;
icon: string;
fileName?: string | null;
}
export interface RecipeNote {
title: string;
text: string;
}
export interface RecipeCommentOut {
recipeId: string;
text: string;
id: string;
createdAt: string;
updatedAt: string;
userId: string;
user: UserBase;
}
export interface UserBase {
id: string;
username?: string | null;
admin: boolean;
fullName?: string | null;
}
export interface RecipeCategoryResponse {
name: string;
id: string;
groupId?: string | null;
slug: string;
recipes?: RecipeSummary[];
}
export interface RecipeSummary {
id?: string | null;
userId?: string;
householdId?: string;
groupId?: string;
name?: string | null;
slug?: string;
image?: unknown;
recipeServings?: number;
recipeYieldQuantity?: number;
recipeYield?: string | null;
totalTime?: string | null;
prepTime?: string | null;
cookTime?: string | null;
performTime?: string | null;
description?: string | null;
recipeCategory?: RecipeCategory[] | null;
tags?: RecipeTag[] | null;
tools?: RecipeTool[];
rating?: number | null;
orgURL?: string | null;
dateAdded?: string | null;
dateUpdated?: string | null;
createdAt?: string | null;
updatedAt?: string | null;
lastMade?: string | null;
}
export interface RecipeCommentCreate {
recipeId: string;
text: string;
}
export interface RecipeCommentSave {
recipeId: string;
text: string;
userId: string;
}
export interface RecipeCommentUpdate {
id: string;
text: string;
}
export interface RecipeDuplicate {
name?: string | null;
}
export interface RecipeIngredientBase {
quantity?: number | null;
unit?: IngredientUnit | CreateIngredientUnit | null;
food?: IngredientFood | CreateIngredientFood | null;
referencedRecipe?: Recipe | null;
note?: string | null;
display?: string;
}
export interface RecipeLastMade {
timestamp: string;
}
export interface RecipeShareToken {
recipeId: string;
expiresAt?: string;
groupId: string;
id: string;
createdAt: string;
recipe: Recipe;
}
export interface RecipeShareTokenCreate {
recipeId: string;
expiresAt?: string;
}
export interface RecipeShareTokenSave {
recipeId: string;
expiresAt?: string;
groupId: string;
}
export interface RecipeShareTokenSummary {
recipeId: string;
expiresAt?: string;
groupId: string;
id: string;
createdAt: string;
}
export interface RecipeSlug {
slug: string;
}
export interface RecipeSuggestionQuery {
orderBy?: string | null;
orderByNullPosition?: OrderByNullPosition | null;
orderDirection?: OrderDirection;
queryFilter?: string | null;
paginationSeed?: string | null;
limit?: number;
maxMissingFoods?: number;
maxMissingTools?: number;
includeFoodsOnHand?: boolean;
includeToolsOnHand?: boolean;
}
export interface RecipeSuggestionResponse {
items: RecipeSuggestionResponseItem[];
}
export interface RecipeSuggestionResponseItem {
recipe: RecipeSummary;
missingFoods: IngredientFood[];
missingTools: RecipeTool[];
}
export interface RecipeTagResponse {
name: string;
id: string;
groupId?: string | null;
slug: string;
recipes?: RecipeSummary[];
}
export interface RecipeTimelineEventCreate {
recipeId: string;
userId: string;
subject: string;
eventType: TimelineEventType;
eventMessage?: string | null;
image?: TimelineEventImage | null;
timestamp?: string;
}
export interface RecipeTimelineEventIn {
recipeId: string;
userId?: string | null;
subject: string;
eventType: TimelineEventType;
eventMessage?: string | null;
image?: TimelineEventImage | null;
timestamp?: string;
}
export interface RecipeTimelineEventOut {
recipeId: string;
userId: string;
subject: string;
eventType: TimelineEventType;
eventMessage?: string | null;
image?: TimelineEventImage | null;
timestamp?: string;
id: string;
groupId: string;
householdId: string;
createdAt: string;
updatedAt: string;
}
export interface RecipeTimelineEventUpdate {
subject: string;
eventMessage?: string | null;
image?: TimelineEventImage | null;
}
export interface RecipeToolCreate {
name: string;
householdsWithTool?: string[];
}
export interface RecipeToolOut {
name: string;
householdsWithTool?: string[];
id: string;
groupId: string;
slug: string;
}
export interface RecipeToolResponse {
name: string;
householdsWithTool?: string[];
id: string;
groupId: string;
slug: string;
recipes?: RecipeSummary[];
}
export interface RecipeToolSave {
name: string;
householdsWithTool?: string[];
groupId: string;
}
export interface SaveIngredientFood {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
labelId?: string | null;
aliases?: CreateIngredientFoodAlias[];
householdsWithIngredientFood?: string[];
groupId: string;
}
export interface SaveIngredientUnit {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
fraction?: boolean;
abbreviation?: string;
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: CreateIngredientUnitAlias[];
standardQuantity?: number | null;
standardUnit?: string | null;
groupId: string;
}
export interface ScrapeRecipe {
includeTags?: boolean;
includeCategories?: boolean;
url: string;
}
export interface ScrapeRecipeBase {
includeTags?: boolean;
includeCategories?: boolean;
}
export interface ScrapeRecipeData {
includeTags?: boolean;
includeCategories?: boolean;
data: string;
url?: string | null;
}
export interface ScrapeRecipeTest {
url: string;
useOpenAI?: boolean;
}
export interface SlugResponse {}
export interface TagIn {
name: string;
}
export interface TagOut {
name: string;
groupId: string;
id: string;
slug: string;
}
export interface TagSave {
name: string;
groupId: string;
}
export interface UnitFoodBase {
id?: string | null;
name: string;
pluralName?: string | null;
description?: string;
extras?: {
[k: string]: unknown;
} | null;
}
export interface UpdateImageResponse {
image: string;
}
export interface RequestQuery {
orderBy?: string | null;
orderByNullPosition?: OrderByNullPosition | null;
orderDirection?: OrderDirection;
queryFilter?: string | null;
paginationSeed?: string | null;
}

View File

@@ -1,49 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type ReportCategory = "backup" | "restore" | "migration" | "bulk_import";
export type ReportSummaryStatus = "in-progress" | "success" | "failure" | "partial";
export interface ReportCreate {
timestamp?: string;
category: ReportCategory;
groupId: string;
name: string;
status?: ReportSummaryStatus;
}
export interface ReportEntryCreate {
reportId: string;
timestamp?: string;
success?: boolean;
message: string;
exception?: string;
}
export interface ReportEntryOut {
reportId: string;
timestamp?: string;
success?: boolean;
message: string;
exception?: string;
id: string;
}
export interface ReportOut {
timestamp?: string;
category: ReportCategory;
groupId: string;
name: string;
status?: ReportSummaryStatus;
id: string;
entries?: ReportEntryOut[];
}
export interface ReportSummary {
timestamp?: string;
category: ReportCategory;
groupId: string;
name: string;
status?: ReportSummaryStatus;
id: string;
}

View File

@@ -1,56 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* 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
*/
export type OrderByNullPosition = "first" | "last";
export type OrderDirection = "asc" | "desc";
export interface ErrorResponse {
message: string;
error?: boolean;
exception?: string | null;
}
export interface FileTokenResponse {
fileToken: string;
}
export interface PaginationQuery {
orderBy?: string | null;
orderByNullPosition?: OrderByNullPosition | null;
orderDirection?: OrderDirection;
queryFilter?: string | null;
paginationSeed?: string | null;
page?: number;
perPage?: number;
}
export interface RecipeSearchQuery {
cookbook?: string | null;
requireAllCategories?: boolean;
requireAllTags?: boolean;
requireAllTools?: boolean;
requireAllFoods?: boolean;
search?: string | null;
}
export interface RequestQuery {
orderBy?: string | null;
orderByNullPosition?: OrderByNullPosition | null;
orderDirection?: OrderDirection;
queryFilter?: string | null;
paginationSeed?: string | null;
}
export interface SSEDataEventBase {}
export interface SSEDataEventDone {
slug: string;
}
export interface SSEDataEventMessage {
message: string;
}
export interface SuccessResponse {
message: string;
error?: boolean;
}
export interface ValidationResponse {
valid: boolean;
}

View File

@@ -1,8 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* 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
*/
export interface _Master_ {}

View File

@@ -1,263 +0,0 @@
/* tslint:disable */
/**
/* 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
*/
export type WebhookType = "mealplan";
export type AuthMethod = "Mealie" | "LDAP" | "OIDC";
export interface ChangePassword {
currentPassword?: string;
newPassword: string;
}
export interface CreateToken {
name: string;
integrationId?: string;
userId: string;
token: string;
}
export interface CreateUserRegistration {
group?: string | null;
household?: string | null;
groupToken?: string | null;
email: string;
username: string;
fullName: string;
password: string;
passwordConfirm: string;
advanced?: boolean;
private?: boolean;
seedData?: boolean;
locale?: string;
}
export interface CredentialsRequest {
username: string;
password: string;
remember_me?: boolean;
}
export interface DeleteTokenResponse {
tokenDelete: string;
}
export interface ForgotPassword {
email: string;
}
export interface GroupBase {
name: string;
}
export interface GroupHouseholdSummary {
id: string;
name: string;
}
export interface GroupInDB {
name: string;
id: string;
slug: string;
categories?: CategoryBase[] | null;
webhooks?: ReadWebhook[];
households?: GroupHouseholdSummary[] | null;
users?: UserSummary[] | null;
preferences?: ReadGroupPreferences | null;
}
export interface CategoryBase {
name: string;
id: string;
groupId?: string | null;
slug: string;
}
export interface ReadWebhook {
enabled?: boolean;
name?: string;
url?: string;
webhookType?: WebhookType;
scheduledTime: string;
groupId: string;
householdId: string;
id: string;
}
export interface UserSummary {
id: string;
groupId: string;
householdId: string;
username: string;
fullName: string;
}
export interface ReadGroupPreferences {
privateGroup?: boolean;
groupId: string;
id: string;
}
export interface GroupSummary {
name: string;
id: string;
slug: string;
preferences?: ReadGroupPreferences | null;
}
export interface LongLiveTokenCreateResponse {
name: string;
id: number;
createdAt?: string | null;
token: string;
}
export interface LongLiveTokenIn {
name: string;
integrationId?: string;
}
export interface LongLiveTokenInDB {
name: string;
integrationId?: string;
userId: string;
token: string;
id: number;
user: PrivateUser;
}
export interface PrivateUser {
id: string;
username?: string | null;
fullName?: string | null;
email: string;
authMethod?: AuthMethod;
admin?: boolean;
group: string;
household: string;
advanced?: boolean;
canInvite?: boolean;
canManage?: boolean;
canManageHousehold?: boolean;
canOrganize?: boolean;
groupId: string;
groupSlug: string;
householdId: string;
householdSlug: string;
tokens?: LongLiveTokenOut[] | null;
cacheKey: string;
password: string;
loginAttemps?: number;
lockedAt?: string | null;
}
export interface LongLiveTokenOut {
name: string;
id: number;
createdAt?: string | null;
}
export interface PasswordResetToken {
token: string;
}
export interface PrivatePasswordResetToken {
userId: string;
token: string;
user: PrivateUser;
}
export interface ResetPassword {
token: string;
email: string;
password: string;
passwordConfirm: string;
}
export interface SavePasswordResetToken {
userId: string;
token: string;
}
export interface Token {
access_token: string;
token_type: string;
}
export interface TokenData {
user_id?: string | null;
username?: string | null;
}
export interface UnlockResults {
unlocked?: number;
}
export interface UpdateGroup {
name: string;
id: string;
slug: string;
categories?: CategoryBase[] | null;
webhooks?: CreateWebhook[];
}
export interface CreateWebhook {
enabled?: boolean;
name?: string;
url?: string;
webhookType?: WebhookType;
scheduledTime: string;
}
export interface UserBase {
id?: string | null;
username?: string | null;
fullName?: string | null;
email: string;
authMethod?: AuthMethod;
admin?: boolean;
group?: string | null;
household?: string | null;
advanced?: boolean;
canInvite?: boolean;
canManage?: boolean;
canManageHousehold?: boolean;
canOrganize?: boolean;
}
export interface UserIn {
id?: string | null;
username: string;
fullName: string;
email: string;
authMethod?: AuthMethod;
admin?: boolean;
group?: string | null;
household?: string | null;
advanced?: boolean;
canInvite?: boolean;
canManage?: boolean;
canManageHousehold?: boolean;
canOrganize?: boolean;
password: string;
}
export interface UserOut {
id: string;
username?: string | null;
fullName?: string | null;
email: string;
authMethod?: AuthMethod;
admin?: boolean;
group: string;
household: string;
advanced?: boolean;
canInvite?: boolean;
canManage?: boolean;
canManageHousehold?: boolean;
canOrganize?: boolean;
groupId: string;
groupSlug: string;
householdId: string;
householdSlug: string;
tokens?: LongLiveTokenOut[] | null;
cacheKey: string;
}
export interface UserRatingCreate {
recipeId: string;
rating?: number | null;
isFavorite?: boolean;
userId: string;
}
export interface UserRatingOut {
recipeId: string;
rating?: number | null;
isFavorite?: boolean;
userId: string;
id: string;
}
export interface UserRatingSummary {
recipeId: string;
rating?: number | null;
isFavorite?: boolean;
}
export interface UserRatingUpdate {
rating?: number | null;
isFavorite?: boolean | null;
}
export interface ValidateResetToken {
token: string;
}

View File

@@ -1,40 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { AllBackups, BackupOptions, CreateBackup } from "~/lib/api/types/admin";
const prefix = "/api";
const routes = {
backupsAvailable: `${prefix}/backups/available`,
backupsExportDatabase: `${prefix}/backups/export/database`,
backupsUpload: `${prefix}/backups/upload`,
backupsFileNameDownload: (fileName: string) => `${prefix}/backups/${fileName}/download`,
backupsFileNameImport: (fileName: string) => `${prefix}/backups/${fileName}/import`,
backupsFileNameDelete: (fileName: string) => `${prefix}/backups/${fileName}/delete`,
};
export class BackupAPI extends BaseAPI {
/** Returns a list of available .zip files for import into Mealie.
*/
async getAll() {
return await this.requests.get<AllBackups>(routes.backupsAvailable);
}
/** Generates a backup of the recipe database in json format.
*/
async createOne(payload: CreateBackup) {
return await this.requests.post(routes.backupsExportDatabase, payload);
}
/** Import a database backup file generated from Mealie.
*/
async restoreDatabase(fileName: string, payload: BackupOptions) {
return await this.requests.post(routes.backupsFileNameImport(fileName), { name: fileName, ...payload });
}
/** Removes a database backup from the file system
*/
async deleteOne(fileName: string) {
return await this.requests.delete(routes.backupsFileNameDelete(fileName));
}
}

View File

@@ -1,25 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { EmailInitationResponse, EmailInvitation } from "~/lib/api/types/household";
import type { ForgotPassword } from "~/lib/api/types/user";
import type { EmailTest } from "~/lib/api/types/admin";
const routes = {
base: "/api/admin/email",
forgotPassword: "/api/users/forgot-password",
invitation: "/api/households/invitations/email",
};
export class EmailAPI extends BaseAPI {
test(payload: EmailTest) {
return this.requests.post<EmailInitationResponse>(routes.base, payload);
}
sendInvitation(payload: EmailInvitation) {
return this.requests.post<EmailInitationResponse>(routes.invitation, payload);
}
sendForgotPassword(payload: ForgotPassword) {
return this.requests.post<EmailInitationResponse>(routes.forgotPassword, payload);
}
}

View File

@@ -1,18 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreateCookBook, ReadCookBook, UpdateCookBook } from "~/lib/api/types/cookbook";
const prefix = "/api";
const routes = {
cookbooks: `${prefix}/households/cookbooks`,
cookbooksId: (id: number) => `${prefix}/households/cookbooks/${id}`,
};
export class CookbookAPI extends BaseCRUDAPI<CreateCookBook, ReadCookBook, UpdateCookBook> {
baseRoute: string = routes.cookbooks;
itemRoute = routes.cookbooksId;
async updateAll(payload: UpdateCookBook[]) {
return await this.requests.put(this.baseRoute, payload);
}
}

View File

@@ -1,22 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { GroupEventNotifierCreate, GroupEventNotifierOut, GroupEventNotifierUpdate } from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
eventNotifier: `${prefix}/households/events/notifications`,
eventNotifierId: (id: string | number) => `${prefix}/households/events/notifications/${id}`,
};
export class GroupEventNotifierApi extends BaseCRUDAPI<
GroupEventNotifierCreate,
GroupEventNotifierOut,
GroupEventNotifierUpdate
> {
baseRoute = routes.eventNotifier;
itemRoute = routes.eventNotifierId;
async test(itemId: string) {
return await this.requests.post(`${this.baseRoute}/${itemId}/test`, {});
}
}

View File

@@ -1,14 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { PlanRulesCreate, PlanRulesOut } from "~/lib/api/types/meal-plan";
const prefix = "/api";
const routes = {
rule: `${prefix}/households/mealplans/rules`,
ruleId: (id: string | number) => `${prefix}/households/mealplans/rules/${id}`,
};
export class MealPlanRulesApi extends BaseCRUDAPI<PlanRulesCreate, PlanRulesOut> {
baseRoute = routes.rule;
itemRoute = routes.ruleId;
}

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreatePlanEntry, CreateRandomEntry, ReadPlanEntry, UpdatePlanEntry } from "~/lib/api/types/meal-plan";
const prefix = "/api";
const routes = {
mealplan: `${prefix}/households/mealplans`,
random: `${prefix}/households/mealplans/random`,
mealplanId: (id: string | number) => `${prefix}/households/mealplans/${id}`,
};
export class MealPlanAPI extends BaseCRUDAPI<CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry> {
baseRoute = routes.mealplan;
itemRoute = routes.mealplanId;
async setRandom(payload: CreateRandomEntry) {
return await this.requests.post<ReadPlanEntry>(routes.random, payload);
}
}

View File

@@ -1,27 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { ReportSummary } from "~/lib/api/types/reports";
import type { SupportedMigrations } from "~/lib/api/types/group";
const prefix = "/api";
export interface MigrationPayload {
addMigrationTag: boolean;
migrationType: SupportedMigrations;
archive: File;
}
const routes = {
base: `${prefix}/groups/migrations`,
};
export class GroupMigrationApi extends BaseAPI {
async startMigration(payload: MigrationPayload) {
const form = new FormData();
form.append("add_migration_tag", String(payload.addMigrationTag));
form.append("migration_type", payload.migrationType);
form.append("archive", payload.archive);
console.log(form);
return await this.requests.post<ReportSummary>(routes.base, form);
}
}

View File

@@ -1,18 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { MultiPurposeLabelCreate, MultiPurposeLabelOut, MultiPurposeLabelUpdate } from "~/lib/api/types/labels";
const prefix = "/api";
const routes = {
labels: `${prefix}/groups/labels`,
labelsId: (id: string | number) => `${prefix}/groups/labels/${id}`,
};
export class MultiPurposeLabelsApi extends BaseCRUDAPI<
MultiPurposeLabelCreate,
MultiPurposeLabelOut,
MultiPurposeLabelUpdate
> {
baseRoute = routes.labels;
itemRoute = routes.labelsId;
}

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreateGroupRecipeAction, GroupRecipeActionOut } from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
groupRecipeActions: `${prefix}/households/recipe-actions`,
groupRecipeActionsId: (id: string | number) => `${prefix}/households/recipe-actions/${id}`,
groupRecipeActionsIdTriggerRecipeSlug: (id: string | number, recipeSlug: string) => `${prefix}/households/recipe-actions/${id}/trigger/${recipeSlug}`,
};
export class GroupRecipeActionsAPI extends BaseCRUDAPI<CreateGroupRecipeAction, GroupRecipeActionOut> {
baseRoute = routes.groupRecipeActions;
itemRoute = routes.groupRecipeActionsId;
async triggerAction(id: string | number, recipeSlug: string, recipeScale: number) {
return await this.requests.post(routes.groupRecipeActionsIdTriggerRecipeSlug(id, recipeSlug), { recipe_scale: recipeScale });
}
}

View File

@@ -1,24 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { ReportCategory, ReportOut, ReportSummary } from "~/lib/api/types/reports";
const prefix = "/api";
const routes = {
base: `${prefix}/groups/reports`,
getOne: (id: string) => `${prefix}/groups/reports/${id}`,
};
export class GroupReportsApi extends BaseAPI {
async getAll(category: ReportCategory | null) {
const query = category ? `?report_type=${category}` : "";
return await this.requests.get<ReportSummary[]>(routes.base + query);
}
async getOne(id: string) {
return await this.requests.get<ReportOut>(routes.getOne(id));
}
async deleteOne(id: string) {
return await this.requests.delete(routes.getOne(id));
}
}

View File

@@ -1,26 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { SuccessResponse } from "~/lib/api/types/response";
import type { SeederConfig } from "~/lib/api/types/group";
const prefix = "/api";
const routes = {
base: `${prefix}/groups/seeders`,
foods: `${prefix}/groups/seeders/foods`,
units: `${prefix}/groups/seeders/units`,
labels: `${prefix}/groups/seeders/labels`,
};
export class GroupDataSeederApi extends BaseAPI {
foods(payload: SeederConfig) {
return this.requests.post<SuccessResponse>(routes.foods, payload);
}
units(payload: SeederConfig) {
return this.requests.post<SuccessResponse>(routes.units, payload);
}
labels(payload: SeederConfig) {
return this.requests.post<SuccessResponse>(routes.labels, payload);
}
}

View File

@@ -1,80 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { ApiRequestInstance } from "~/lib/api/types/non-generated";
import type {
ShoppingListAddRecipeParamsBulk,
ShoppingListCreate,
ShoppingListItemCreate,
ShoppingListItemOut,
ShoppingListItemUpdateBulk,
ShoppingListMultiPurposeLabelUpdate,
ShoppingListOut,
ShoppingListUpdate,
} from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
shoppingLists: `${prefix}/households/shopping/lists`,
shoppingListsId: (id: string) => `${prefix}/households/shopping/lists/${id}`,
shoppingListIdAddRecipe: (id: string) => `${prefix}/households/shopping/lists/${id}/recipe`,
shoppingListIdRemoveRecipe: (id: string, recipeId: string) => `${prefix}/households/shopping/lists/${id}/recipe/${recipeId}/delete`,
shoppingListIdUpdateLabelSettings: (id: string) => `${prefix}/households/shopping/lists/${id}/label-settings`,
shoppingListItems: `${prefix}/households/shopping/items`,
shoppingListItemsCreateBulk: `${prefix}/households/shopping/items/create-bulk`,
shoppingListItemsId: (id: string) => `${prefix}/households/shopping/items/${id}`,
};
export class ShoppingListsApi extends BaseCRUDAPI<ShoppingListCreate, ShoppingListOut, ShoppingListUpdate> {
baseRoute = routes.shoppingLists;
itemRoute = routes.shoppingListsId;
async addRecipes(itemId: string, data: ShoppingListAddRecipeParamsBulk[]) {
return await this.requests.post(routes.shoppingListIdAddRecipe(itemId), data);
}
async removeRecipe(itemId: string, recipeId: string, recipeDecrementQuantity = 1) {
return await this.requests.post(routes.shoppingListIdRemoveRecipe(itemId, recipeId), { recipeDecrementQuantity });
}
async updateLabelSettings(itemId: string, listSettings: ShoppingListMultiPurposeLabelUpdate[]) {
return await this.requests.put(routes.shoppingListIdUpdateLabelSettings(itemId), listSettings);
}
}
export class ShoppingListItemsApi extends BaseCRUDAPI<
ShoppingListItemCreate,
ShoppingListItemOut,
ShoppingListItemUpdateBulk
> {
baseRoute = routes.shoppingListItems;
itemRoute = routes.shoppingListItemsId;
async createMany(items: ShoppingListItemCreate[]) {
return await this.requests.post(routes.shoppingListItemsCreateBulk, items);
}
async updateMany(items: ShoppingListItemOut[]) {
return await this.requests.put(routes.shoppingListItems, items);
}
async deleteMany(items: ShoppingListItemOut[]) {
let query = "?";
items.forEach((item) => {
query += `ids=${item.id}&`;
});
return await this.requests.delete(routes.shoppingListItems + query);
}
}
export class ShoppingApi {
public lists: ShoppingListsApi;
public items: ShoppingListItemsApi;
constructor(requests: ApiRequestInstance) {
this.lists = new ShoppingListsApi(requests);
this.items = new ShoppingListItemsApi(requests);
}
}

View File

@@ -1,20 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreateWebhook, ReadWebhook } from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
webhooks: `${prefix}/households/webhooks`,
webhooksId: (id: string | number) => `${prefix}/households/webhooks/${id}`,
webhooksIdTest: (id: string | number) => `${prefix}/households/webhooks/${id}/test`,
};
export class WebhooksAPI extends BaseCRUDAPI<CreateWebhook, ReadWebhook> {
baseRoute = routes.webhooks;
itemRoute = routes.webhooksId;
itemTestRoute = routes.webhooksIdTest;
async testOne(itemId: string | number) {
return await this.requests.post<null>(`${this.itemTestRoute(itemId)}`, {});
}
}

View File

@@ -1,48 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { PaginationData } from "../types/non-generated";
import type { QueryValue } from "../base/route";
import type { GroupBase, GroupInDB, GroupSummary, UserSummary } from "~/lib/api/types/user";
import type {
GroupAdminUpdate,
GroupStorage,
ReadGroupPreferences,
UpdateGroupPreferences,
} from "~/lib/api/types/group";
const prefix = "/api";
const routes = {
groups: `${prefix}/admin/groups`,
groupsSelf: `${prefix}/groups/self`,
preferences: `${prefix}/groups/preferences`,
storage: `${prefix}/groups/storage`,
members: `${prefix}/groups/members`,
groupsId: (id: string | number) => `${prefix}/admin/groups/${id}`,
};
export class GroupAPI extends BaseCRUDAPI<GroupBase, GroupInDB, GroupAdminUpdate> {
baseRoute = routes.groups;
itemRoute = routes.groupsId;
/** Returns the Group Data for the Current User
*/
async getCurrentUserGroup() {
return await this.requests.get<GroupSummary>(routes.groupsSelf);
}
async getPreferences() {
return await this.requests.get<ReadGroupPreferences>(routes.preferences);
}
async setPreferences(payload: UpdateGroupPreferences) {
// TODO: This should probably be a patch request, which isn't offered by the API currently
return await this.requests.put<ReadGroupPreferences, UpdateGroupPreferences>(routes.preferences, payload);
}
async fetchMembers(page = 1, perPage = -1, params = {} as Record<string, QueryValue>) {
return await this.requests.get<PaginationData<UserSummary>>(routes.members, { page, perPage, ...params });
}
async storage() {
return await this.requests.get<GroupStorage>(routes.storage);
}
}

View File

@@ -1,71 +0,0 @@
import { BaseCRUDAPIReadOnly } from "../base/base-clients";
import type { PaginationData } from "../types/non-generated";
import type { QueryValue } from "../base/route";
import type { UserOut } from "~/lib/api/types/user";
import type {
HouseholdInDB,
HouseholdStatistics,
ReadHouseholdPreferences,
SetPermissions,
UpdateHouseholdPreferences,
CreateInviteToken,
ReadInviteToken,
HouseholdSummary,
HouseholdRecipeSummary,
} from "~/lib/api/types/household";
const prefix = "/api";
const routes = {
households: `${prefix}/groups/households`,
householdsSelf: `${prefix}/households/self`,
members: `${prefix}/households/members`,
permissions: `${prefix}/households/permissions`,
preferences: `${prefix}/households/preferences`,
statistics: `${prefix}/households/statistics`,
invitation: `${prefix}/households/invitations`,
householdsId: (id: string | number) => `${prefix}/groups/households/${id}`,
householdsSelfRecipesSlug: (recipeSlug: string) => `${prefix}/households/self/recipes/${recipeSlug}`,
};
export class HouseholdAPI extends BaseCRUDAPIReadOnly<HouseholdSummary> {
baseRoute = routes.households;
itemRoute = routes.householdsId;
/** Returns the Household Data for the Current User
*/
async getCurrentUserHousehold() {
return await this.requests.get<HouseholdInDB>(routes.householdsSelf);
}
async getCurrentUserHouseholdRecipe(recipeSlug: string) {
return await this.requests.get<HouseholdRecipeSummary>(routes.householdsSelfRecipesSlug(recipeSlug));
}
async getPreferences() {
return await this.requests.get<ReadHouseholdPreferences>(routes.preferences);
}
async setPreferences(payload: UpdateHouseholdPreferences) {
// TODO: This should probably be a patch request, which isn't offered by the API currently
return await this.requests.put<ReadHouseholdPreferences, UpdateHouseholdPreferences>(routes.preferences, payload);
}
async createInvitation(payload: CreateInviteToken) {
return await this.requests.post<ReadInviteToken>(routes.invitation, payload);
}
async fetchMembers(page = 1, perPage = -1, params = {} as Record<string, QueryValue>) {
return await this.requests.get<PaginationData<UserOut>>(routes.members, { page, perPage, ...params });
}
async setMemberPermissions(payload: SetPermissions) {
// TODO: This should probably be a patch request, which isn't offered by the API currently
return await this.requests.put<UserOut, SetPermissions>(routes.permissions, payload);
}
async statistics() {
return await this.requests.get<HouseholdStatistics>(routes.statistics);
}
}

View File

@@ -1,20 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import { config } from "../config";
import type { CategoryIn, RecipeCategoryResponse } from "~/lib/api/types/recipe";
const prefix = config.PREFIX + "/organizers";
const routes = {
categories: `${prefix}/categories`,
categoriesId: (category: string) => `${prefix}/categories/${category}`,
categoriesSlug: (category: string) => `${prefix}/categories/slug/${category}`,
};
export class CategoriesAPI extends BaseCRUDAPI<CategoryIn, RecipeCategoryResponse> {
baseRoute: string = routes.categories;
itemRoute = routes.categoriesId;
async bySlug(slug: string) {
return await this.requests.get<RecipeCategoryResponse>(routes.categoriesSlug(slug));
}
}

View File

@@ -1,20 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import { config } from "../config";
import type { RecipeTagResponse, TagIn } from "~/lib/api/types/recipe";
const prefix = config.PREFIX + "/organizers";
const routes = {
tags: `${prefix}/tags`,
tagsId: (tag: string) => `${prefix}/tags/${tag}`,
tagsSlug: (tag: string) => `${prefix}/tags/slug/${tag}`,
};
export class TagsAPI extends BaseCRUDAPI<TagIn, RecipeTagResponse> {
baseRoute: string = routes.tags;
itemRoute = routes.tagsId;
async bySlug(slug: string) {
return await this.requests.get<RecipeTagResponse>(routes.tagsSlug(slug));
}
}

View File

@@ -1,20 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import { config } from "../config";
import type { RecipeTool, RecipeToolCreate, RecipeToolResponse } from "~/lib/api/types/recipe";
const prefix = config.PREFIX + "/organizers";
const routes = {
tools: `${prefix}/tools`,
toolsId: (id: string) => `${prefix}/tools/${id}`,
toolsSlug: (id: string) => `${prefix}/tools/slug/${id}`,
};
export class ToolsApi extends BaseCRUDAPI<RecipeToolCreate, RecipeTool> {
baseRoute: string = routes.tools;
itemRoute = routes.toolsId;
async bySlug(slug: string) {
return await this.requests.get<RecipeToolResponse>(routes.toolsSlug(slug));
}
}

View File

@@ -1,48 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { AssignCategories, AssignSettings, AssignTags, DeleteRecipes, ExportRecipes } from "~/lib/api/types/recipe";
import type { GroupDataExport } from "~/lib/api/types/group";
// Many bulk actions return nothing
type BulkActionResponse = object;
const prefix = "/api";
const routes = {
bulkExport: prefix + "/recipes/bulk-actions/export",
purgeExports: prefix + "/recipes/bulk-actions/export/purge",
bulkCategorize: prefix + "/recipes/bulk-actions/categorize",
bulkTag: prefix + "/recipes/bulk-actions/tag",
bulkDelete: prefix + "/recipes/bulk-actions/delete",
bulkSettings: prefix + "/recipes/bulk-actions/settings",
};
export class BulkActionsAPI extends BaseAPI {
async bulkExport(payload: ExportRecipes) {
return await this.requests.post<BulkActionResponse>(routes.bulkExport, payload);
}
async bulkCategorize(payload: AssignCategories) {
return await this.requests.post<BulkActionResponse>(routes.bulkCategorize, payload);
}
async bulkSetSettings(payload: AssignSettings) {
return await this.requests.post<BulkActionResponse>(routes.bulkSettings, payload);
}
async bulkTag(payload: AssignTags) {
return await this.requests.post<BulkActionResponse>(routes.bulkTag, payload);
}
async bulkDelete(payload: DeleteRecipes) {
return await this.requests.post<BulkActionResponse>(routes.bulkDelete, payload);
}
async fetchExports() {
return await this.requests.get<GroupDataExport[]>(routes.bulkExport);
}
async purgeExports() {
return await this.requests.delete<BulkActionResponse>(routes.purgeExports);
}
}

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreateIngredientFood, IngredientFood } from "~/lib/api/types/recipe";
const prefix = "/api";
const routes = {
food: `${prefix}/foods`,
foodsFood: (tag: string) => `${prefix}/foods/${tag}`,
merge: `${prefix}/foods/merge`,
};
export class FoodAPI extends BaseCRUDAPI<CreateIngredientFood, IngredientFood> {
baseRoute: string = routes.food;
itemRoute = routes.foodsFood;
merge(fromId: string, toId: string) {
return this.requests.put<IngredientFood>(routes.merge, { fromFood: fromId, toFood: toId });
}
}

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type { CreateIngredientUnit, IngredientUnit } from "~/lib/api/types/recipe";
const prefix = "/api";
const routes = {
unit: `${prefix}/units`,
unitsUnit: (tag: string) => `${prefix}/units/${tag}`,
merge: `${prefix}/units/merge`,
};
export class UnitAPI extends BaseCRUDAPI<CreateIngredientUnit, IngredientUnit> {
baseRoute: string = routes.unit;
itemRoute = routes.unitsUnit;
merge(fromId: string, toId: string) {
return this.requests.put<IngredientUnit>(routes.merge, { fromUnit: fromId, toUnit: toId });
}
}

View File

@@ -1 +0,0 @@
export { RecipeAPI } from "./recipe";

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../../base/base-clients";
import type { RecipeCommentCreate, RecipeCommentOut, RecipeCommentUpdate } from "~/lib/api/types/recipe";
const prefix = "/api";
const routes = {
comment: `${prefix}/comments`,
byRecipe: (id: string) => `${prefix}/recipes/${id}/comments`,
commentsId: (id: string) => `${prefix}/comments/${id}`,
};
export class CommentsApi extends BaseCRUDAPI<RecipeCommentCreate, RecipeCommentOut, RecipeCommentUpdate> {
baseRoute: string = routes.comment;
itemRoute = routes.commentsId;
async byRecipe(slug: string) {
return await this.requests.get<RecipeCommentOut[]>(routes.byRecipe(slug));
}
}

View File

@@ -1,19 +0,0 @@
import { BaseCRUDAPI } from "../../base/base-clients";
import type { RecipeShareToken, RecipeShareTokenCreate } from "~/lib/api/types/recipe";
const prefix = "/api";
const routes = {
shareToken: `${prefix}/shared/recipes`,
shareTokenId: (id: string) => `${prefix}/shared/recipes/${id}`,
shareTokenIdZip: (id: string) => `${prefix}/recipes/shared/${id}/zip`,
};
export class RecipeShareApi extends BaseCRUDAPI<RecipeShareTokenCreate, RecipeShareToken> {
baseRoute: string = routes.shareToken;
itemRoute = routes.shareTokenId;
getZipRedirectUrl(tokenId: string) {
return routes.shareTokenIdZip(tokenId);
}
}

View File

@@ -1,283 +0,0 @@
import { SSE } from "sse.js";
import type { SSEvent } from "sse.js";
import { BaseCRUDAPI } from "../../base/base-clients";
import { route } from "../../base";
import { CommentsApi } from "./recipe-comments";
import { RecipeShareApi } from "./recipe-share";
import type {
Recipe,
CreateRecipe,
RecipeAsset,
CreateRecipeByUrlBulk,
ParsedIngredient,
UpdateImageResponse,
RecipeLastMade,
RecipeSuggestionQuery,
RecipeSuggestionResponse,
RecipeTimelineEventIn,
RecipeTimelineEventOut,
RecipeTimelineEventUpdate,
} from "~/lib/api/types/recipe";
import type { SSEDataEventDone, SSEDataEventMessage } from "~/lib/api/types/response";
import type { ApiRequestInstance, PaginationData, RequestResponse } from "~/lib/api/types/non-generated";
import { SSEDataEventStatus } from "~/lib/api/types/non-generated";
export type Parser = "nlp" | "brute" | "openai";
export interface CreateAsset {
name: string;
icon: string;
extension: string;
file: File;
}
const prefix = "/api";
const routes = {
recipesCreate: `${prefix}/recipes/create`,
recipesBase: `${prefix}/recipes`,
recipesSuggestions: `${prefix}/recipes/suggestions`,
recipesTestScrapeUrl: `${prefix}/recipes/test-scrape-url`,
recipesCreateUrl: `${prefix}/recipes/create/url/stream`,
recipesCreateUrlBulk: `${prefix}/recipes/create/url/bulk`,
recipesCreateFromZip: `${prefix}/recipes/create/zip`,
recipesCreateFromImage: `${prefix}/recipes/create/image`,
recipesCreateFromHtmlOrJson: `${prefix}/recipes/create/html-or-json/stream`,
recipesCategory: `${prefix}/recipes/category`,
recipesParseIngredient: `${prefix}/parser/ingredient`,
recipesParseIngredients: `${prefix}/parser/ingredients`,
recipesTimelineEvent: `${prefix}/recipes/timeline/events`,
recipesRecipeSlug: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}`,
recipesRecipeSlugImage: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}/image`,
recipesRecipeSlugAssets: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}/assets`,
recipesSlugComments: (slug: string) => `${prefix}/recipes/${slug}/comments`,
recipesSlugCommentsId: (slug: string, id: number) => `${prefix}/recipes/${slug}/comments/${id}`,
recipesSlugLastMade: (slug: string) => `${prefix}/recipes/${slug}/last-made`,
recipesTimelineEventId: (id: string) => `${prefix}/recipes/timeline/events/${id}`,
recipesTimelineEventIdImage: (id: string) => `${prefix}/recipes/timeline/events/${id}/image`,
};
export type RecipeSearchQuery = {
search?: string;
orderDirection?: "asc" | "desc";
groupId?: string;
queryFilter?: string;
cookbook?: string;
households?: string[];
categories?: string[];
requireAllCategories?: boolean;
tags?: string[];
requireAllTags?: boolean;
tools?: string[];
requireAllTools?: boolean;
foods?: string[];
requireAllFoods?: boolean;
page?: number;
perPage?: number;
orderBy?: string;
orderByNullPosition?: "first" | "last";
_searchSeed?: string;
};
export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
baseRoute: string = routes.recipesBase;
itemRoute = routes.recipesRecipeSlug;
comments: CommentsApi;
share: RecipeShareApi;
constructor(requests: ApiRequestInstance) {
super(requests);
this.comments = new CommentsApi(requests);
this.share = new RecipeShareApi(requests);
}
async search(rsq: RecipeSearchQuery) {
return await this.requests.get<PaginationData<Recipe>>(route(routes.recipesBase, rsq));
}
async getAllByCategory(categories: string[]) {
return await this.requests.get<Recipe[]>(routes.recipesCategory, {
categories,
});
}
async getSuggestions(q: RecipeSuggestionQuery, foods: string[] | null = null, tools: string[] | null = null) {
return await this.requests.get<RecipeSuggestionResponse>(
route(routes.recipesSuggestions, { ...q, foods, tools }),
);
}
async createAsset(recipeSlug: string, payload: CreateAsset) {
const formData = new FormData();
formData.append("file", payload.file);
formData.append("name", payload.name);
formData.append("extension", payload.extension);
formData.append("icon", payload.icon);
return await this.requests.post<RecipeAsset>(routes.recipesRecipeSlugAssets(recipeSlug), formData);
}
updateImage(slug: string, fileObject: File) {
const formData = new FormData();
formData.append("image", fileObject);
formData.append("extension", fileObject.name.split(".").pop() ?? "");
return this.requests.put<UpdateImageResponse, FormData>(routes.recipesRecipeSlugImage(slug), formData);
}
updateImagebyURL(slug: string, url: string) {
return this.requests.post<UpdateImageResponse>(routes.recipesRecipeSlugImage(slug), { url });
}
deleteImage(slug: string) {
return this.requests.delete<string>(routes.recipesRecipeSlugImage(slug));
}
async testCreateOneUrl(url: string, useOpenAI = false) {
return await this.requests.post<Recipe | null>(routes.recipesTestScrapeUrl, { url, useOpenAI });
}
private streamRecipeCreate(streamRoute: string, payload: object, onProgress?: (message: string) => void): Promise<RequestResponse<string>> {
return new Promise((resolve) => {
const { token } = useMealieAuth();
const sse = new SSE(streamRoute, {
headers: {
"Content-Type": "application/json",
...(token.value ? { Authorization: `Bearer ${token.value}` } : {}),
},
payload: JSON.stringify(payload),
withCredentials: true,
autoReconnect: false,
});
if (onProgress) {
sse.addEventListener(SSEDataEventStatus.Progress, (e: SSEvent) => {
const { message } = JSON.parse(e.data) as SSEDataEventMessage;
onProgress(message);
});
}
sse.addEventListener(SSEDataEventStatus.Done, (e: SSEvent) => {
const { slug } = JSON.parse(e.data) as SSEDataEventDone;
sse.close();
resolve({ response: { status: 201, data: slug } as any, data: slug, error: null });
});
sse.addEventListener(SSEDataEventStatus.Error, (e: SSEvent) => {
try {
const { message } = JSON.parse(e.data) as SSEDataEventMessage;
sse.close();
resolve({ response: null, data: null, error: new Error(message) });
}
catch {
// Not a backend error payload (e.g. XHR connection-close event); ignore
}
});
sse.stream();
});
}
async createOneByHtmlOrJson(
data: string,
includeTags: boolean,
includeCategories: boolean,
url: string | null = null,
onProgress?: (message: string) => void,
): Promise<RequestResponse<string>> {
return this.streamRecipeCreate(routes.recipesCreateFromHtmlOrJson, { data, includeTags, includeCategories, url }, onProgress);
}
async createOneByUrl(
url: string,
includeTags: boolean,
includeCategories: boolean,
onProgress?: (message: string) => void,
): Promise<RequestResponse<string>> {
return this.streamRecipeCreate(routes.recipesCreateUrl, { url, includeTags, includeCategories }, onProgress);
}
async createManyByUrl(payload: CreateRecipeByUrlBulk) {
return await this.requests.post<string>(routes.recipesCreateUrlBulk, payload);
}
async createOneFromImages(fileObjects: (Blob | File)[], translateLanguage: string | null = null) {
const formData = new FormData();
fileObjects.forEach((file) => {
formData.append("images", file);
});
let apiRoute = routes.recipesCreateFromImage;
if (translateLanguage) {
apiRoute = `${apiRoute}?translateLanguage=${translateLanguage}`;
}
return await this.requests.post<string>(apiRoute, formData);
}
async parseIngredients(parser: Parser, ingredients: Array<string>) {
parser = parser || "nlp";
return await this.requests.post<ParsedIngredient[]>(routes.recipesParseIngredients, { parser, ingredients });
}
async parseIngredient(parser: Parser, ingredient: string) {
parser = parser || "nlp";
return await this.requests.post<ParsedIngredient>(routes.recipesParseIngredient, { parser, ingredient });
}
async updateMany(payload: Recipe[]) {
return await this.requests.put<Recipe[]>(routes.recipesBase, payload);
}
async patchMany(payload: Recipe[]) {
return await this.requests.patch<Recipe[]>(routes.recipesBase, payload);
}
async updateLastMade(recipeSlug: string, timestamp: string) {
return await this.requests.patch<Recipe, RecipeLastMade>(routes.recipesSlugLastMade(recipeSlug), { timestamp });
}
async createTimelineEvent(payload: RecipeTimelineEventIn) {
return await this.requests.post<RecipeTimelineEventOut>(routes.recipesTimelineEvent, payload);
}
async updateTimelineEvent(eventId: string, payload: RecipeTimelineEventUpdate) {
return await this.requests.put<RecipeTimelineEventOut, RecipeTimelineEventUpdate>(
routes.recipesTimelineEventId(eventId),
payload,
);
}
async deleteTimelineEvent(eventId: string) {
return await this.requests.delete<RecipeTimelineEventOut>(routes.recipesTimelineEventId(eventId));
}
async getAllTimelineEvents(page = 1, perPage = -1, params = {} as any) {
return await this.requests.get<PaginationData<RecipeTimelineEventOut>>(
routes.recipesTimelineEvent, { page, perPage, ...params },
);
}
async updateTimelineEventImage(eventId: string, fileObject: Blob | File, fileName: string) {
const formData = new FormData();
formData.append("image", fileObject);
formData.append("extension", fileName.split(".").pop() ?? "");
return await this.requests.put<UpdateImageResponse, FormData>(routes.recipesTimelineEventIdImage(eventId), formData);
}
}

View File

@@ -1,9 +0,0 @@
import { BaseAPI } from "../base/base-clients";
export class UploadFile extends BaseAPI {
file(url: string, fileObject: any) {
const { $axios } = useNuxtApp();
return $axios.post<string>(url, fileObject, { headers: { "Content-Type": "multipart/form-data" } });
// return this.requests.post<string>(url, fileObject);
}
}

View File

@@ -1,14 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { CreateUserRegistration } from "~/lib/api/types/user";
const prefix = "/api";
const routes = {
register: `${prefix}/users/register`,
};
export class RegisterAPI extends BaseAPI {
async register(payload: CreateUserRegistration) {
return await this.requests.post<any>(routes.register, payload);
}
}

View File

@@ -1,98 +0,0 @@
import { BaseCRUDAPI } from "../base/base-clients";
import type {
ChangePassword,
DeleteTokenResponse,
LongLiveTokenIn,
LongLiveTokenOut,
ResetPassword,
UserBase,
UserIn,
UserOut,
UserRatingOut,
UserRatingSummary,
} from "~/lib/api/types/user";
export interface UserRatingsSummaries {
ratings: UserRatingSummary[];
}
export interface UserRatingsOut {
ratings: UserRatingOut[];
}
const prefix = "/api";
const routes = {
usersSelf: `${prefix}/users/self`,
ratingsSelf: `${prefix}/users/self/ratings`,
passwordReset: `${prefix}/users/reset-password`,
passwordChange: `${prefix}/users/password`,
users: `${prefix}/users`,
usersIdImage: (id: string) => `${prefix}/users/${id}/image`,
usersIdResetPassword: (id: string) => `${prefix}/users/${id}/reset-password`,
usersId: (id: string) => `${prefix}/users/${id}`,
usersIdFavorites: (id: string) => `${prefix}/users/${id}/favorites`,
usersIdFavoritesSlug: (id: string, slug: string) => `${prefix}/users/${id}/favorites/${slug}`,
usersIdRatings: (id: string) => `${prefix}/users/${id}/ratings`,
usersIdRatingsSlug: (id: string, slug: string) => `${prefix}/users/${id}/ratings/${slug}`,
usersSelfFavoritesId: (id: string) => `${prefix}/users/self/favorites/${id}`,
usersSelfRatingsId: (id: string) => `${prefix}/users/self/ratings/${id}`,
usersApiTokens: `${prefix}/users/api-tokens`,
usersApiTokensTokenId: (token_id: string | number) => `${prefix}/users/api-tokens/${token_id}`,
};
export class UserApi extends BaseCRUDAPI<UserIn, UserOut, UserBase> {
baseRoute: string = routes.users;
itemRoute = (itemid: string) => routes.usersId(itemid);
async addFavorite(id: string, slug: string) {
return await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {});
}
async removeFavorite(id: string, slug: string) {
return await this.requests.delete(routes.usersIdFavoritesSlug(id, slug));
}
async getFavorites(id: string) {
return await this.requests.get<UserRatingsOut>(routes.usersIdFavorites(id));
}
async getSelfFavorites() {
return await this.requests.get<UserRatingsSummaries>(routes.ratingsSelf);
}
async getRatings(id: string) {
return await this.requests.get<UserRatingsOut>(routes.usersIdRatings(id));
}
async setRating(id: string, slug: string, rating: number | null, isFavorite: boolean | null) {
return await this.requests.post(routes.usersIdRatingsSlug(id, slug), { rating, isFavorite });
}
async getSelfRatings() {
return await this.requests.get<UserRatingsSummaries>(routes.ratingsSelf);
}
async changePassword(changePassword: ChangePassword) {
return await this.requests.put(routes.passwordChange, changePassword);
}
async createAPIToken(tokenName: LongLiveTokenIn) {
return await this.requests.post<LongLiveTokenOut>(routes.usersApiTokens, tokenName);
}
async deleteAPIToken(tokenId: number) {
return await this.requests.delete<DeleteTokenResponse>(routes.usersApiTokensTokenId(tokenId));
}
userProfileImage(id: string) {
if (!id || id === undefined) return;
return `/api/users/${id}/image`;
}
async resetPassword(payload: ResetPassword) {
return await this.requests.post(routes.passwordReset, payload);
}
}

View File

@@ -1,20 +0,0 @@
import { BaseAPI } from "../base/base-clients";
import type { FileTokenResponse } from "~/lib/api/types/response";
const prefix = "/api";
export class UtilsAPI extends BaseAPI {
async download(url: string) {
const { response } = await this.requests.get<FileTokenResponse>(url);
if (!response) {
return;
}
const token: string = response.data.fileToken;
const tokenURL = prefix + "/utils/download?token=" + token;
window.open(tokenURL, "_blank");
return response;
}
}