node-mealie
A Node.js wrapper for the Mealie API with TypeScript support, Deno compatibility, and ESM module support.
Features
- 🚀 TypeScript support
- 📦 ESM and CommonJS compatible
- 🦕 Deno compatible
- 🔒 Authentication handling (Username/Password, OAuth/OIDC)
- 🧪 100% test coverage
- 🛠️ Extensible architecture
Installation
npm install node-mealie
Usage
Basic Usage
import { AboutService } from 'node-mealie';
const client = new AboutService({
baseUrl: 'https://demo.mealie.io', // optional, defaults to demo instance
});
// Get app info
const appInfo = await client.getAppInfo();
console.log(appInfo.version);
// Get startup info
const startupInfo = await client.getStartupInfo();
console.log(startupInfo.isDemo);
// Get app theme
const theme = await client.getAppTheme();
console.log(theme);
Groups Management
import { MealieClient, GroupsService } from 'node-mealie';
const client = new MealieClient({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
const groups = new GroupsService(client);
// Get current group
const currentGroup = await groups.getSelf();
// Get all households
const households = await groups.getAllHouseholds({
page: 1,
perPage: 10,
orderBy: 'name',
orderDirection: 'asc'
});
// Get group members
const members = await groups.getGroupMembers();
// Check storage usage
const storage = await groups.getStorage();
console.log(`Using ${storage.usedStorageStr} of ${storage.totalStorageStr}`);
// Manage labels
const label = await groups.createLabel({ name: 'Vegetarian' });
const labels = await groups.getAllLabels({ search: 'veg' });
// Start data migration
const migrationFile = new File(['...data...'], 'migration.zip');
const report = await groups.startDataMigration({
migration_type: 'chowdown',
archive: migrationFile
});
Households Management
import { MealieClient, HouseholdsService } from 'node-mealie';
const client = new MealieClient({
baseUrl: 'https://your-mealie-instance.com',
username: 'your-username',
password: 'your-password'
});
const households = new HouseholdsService(client);
// Create a cookbook
const cookbook = await households.createCookbook({
name: 'Italian Recipes',
description: 'A collection of Italian dishes',
public: true
});
// Create a shopping list
const shoppingList = await households.createShoppingList({
name: 'Weekly Groceries'
});
// Add items to shopping list
const item = await households.createShoppingListItem({
shoppingListId: shoppingList.id,
note: 'Milk',
quantity: 1
});
// Create a meal plan
const mealPlan = await households.createMealplan({
date: '2025-04-25',
entryType: 'dinner',
title: 'Pasta Night'
});
// Get household statistics
const stats = await households.getStatistics();
console.log(`Total recipes: ${stats.totalRecipes}`);
Authentication
import { AuthService } from 'node-mealie';
const auth = new AuthService({
baseUrl: 'https://your-mealie-instance.com'
});
// Standard login
const token = await auth.login('username', 'password');
// OAuth/OIDC login
const { redirectUrl } = await auth.oauthLogin();
// Redirect user to OAuth provider...
// Handle OAuth callback
const callbackToken = await auth.oauthCallback({ code: 'auth-code' });
// Refresh token
const newToken = await auth.refreshToken();
// Logout
await auth.logout();
With Existing Token
import { AboutService } from 'node-mealie';
// Use existing token
const client = new AboutService();
client.setToken('your-auth-token');
Deno Usage
import { AboutService } from "https://deno.land/x/node_mealie/mod.ts";
const client = new AboutService();
const appInfo = await client.getAppInfo();
console.log(appInfo.version);
API Reference
AboutService
getAppInfo()
: Get general application informationgetStartupInfo()
: Get startup informationgetAppTheme()
: Get current theme settings
AuthService
login(username: string, password: string)
: Authenticate with credentialsoauthLogin()
: Initiate OAuth login flowoauthCallback(params: OAuthCallbackParams)
: Handle OAuth callbackrefreshToken()
: Refresh authentication tokenlogout()
: Log out the current usersetToken(token: string)
: Set authentication token manuallyclearToken()
: Clear authentication token
HouseholdsService
The HouseholdsService
provides comprehensive functionality for managing household-related features:
Cookbooks
getCookbooks(params?)
: Get all cookbookscreateCookbook(data)
: Create a new cookbookupdateCookbook(id, data)
: Update a cookbookdeleteCookbook(id)
: Delete a cookbook
Shopping Lists
getShoppingLists(params?)
: Get all shopping listscreateShoppingList(data)
: Create a new shopping listcreateShoppingListItem(data)
: Add item to a listupdateShoppingListItem(id, data)
: Update an itemaddRecipeIngredientsToList(id, data)
: Add recipe ingredients to list
Meal Plans
getMealplans(params?)
: Get meal planscreateMealplan(data)
: Create a meal plangetTodaysMeals()
: Get today's meal planscreateRandomMeal(data)
: Create a random meal plancreateMealplanRule(data)
: Create meal plan rules
Household Management
getSelf()
: Get current household informationgetHouseholdPreferences()
: Get household preferencesupdateHouseholdPreferences(data)
: Update preferencessetMemberPermissions(data)
: Set member permissionsgetStatistics()
: Get household statistics
Invitations
getInviteTokens()
: Get all invite tokenscreateInviteToken(data)
: Create new invite tokenemailInvitation(data)
: Send email invitation
GroupsService
The GroupsService
provides functionality for managing groups, households, migrations, reports, and more:
Group Information
getSelf()
: Get current group informationgetGroupMembers(params?)
: Get members in the groupgetGroupMember(usernameOrId)
: Get specific member detailsgetGroupPreferences()
: Get group preferencesupdateGroupPreferences(data)
: Update group preferencesgetStorage()
: Get storage usage information
Households
getAllHouseholds(params?)
: Get all households within a groupgetOneHousehold(householdSlug)
: Get specific household details
Migrations
startDataMigration(params)
: Import data from other platforms (Nextcloud, Chowdown, etc.)
Reports
getAllReports(reportType?)
: Get all reports or filter by typegetOneReport(itemId)
: Get specific report detailsdeleteOneReport(itemId)
: Delete a report
Multi-Purpose Labels
createLabel(data)
: Create a new labelgetAllLabels(params?)
: Get all labels with optional searchgetOneLabel(itemId)
: Get specific labelupdateLabel(itemId, data)
: Update a labeldeleteLabel(itemId)
: Delete a label
Seeders
seedFoods(config)
: Initialize food dataseedLabels(config)
: Initialize label dataseedUnits(config)
: Initialize unit data
OrganizerService
The OrganizerService
provides functionality for managing recipe organization features including categories, tags, and tools:
Categories
getAllCategories(params?)
: Get all categories with optional pagination and filteringcreateCategory(data)
: Create a new categorygetAllEmptyCategories()
: Get all categories without recipesgetCategoryById(id)
: Get specific category by IDupdateCategory(id, data)
: Update a categorydeleteCategory(id)
: Delete a categorygetCategoryBySlug(slug)
: Get category by slug
Tags
getAllTags(params?)
: Get all tags with optional pagination and filteringcreateTag(data)
: Create a new taggetEmptyTags()
: Get all tags without recipesgetTagById(id)
: Get specific tag by IDupdateTag(id, data)
: Update a tagdeleteTag(id)
: Delete a taggetTagBySlug(slug)
: Get tag by slug
Tools
getAllTools(params?)
: Get all tools with optional pagination and filteringcreateTool(data)
: Create a new toolgetToolById(id)
: Get specific tool by IDupdateTool(id, data)
: Update a tooldeleteTool(id)
: Delete a toolgetToolBySlug(slug)
: Get tool by slug
import { OrganizerService } from 'node-mealie';
const organizers = new OrganizerService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
// Work with categories
const categories = await organizers.getAllCategories({ search: 'breakfast' });
const newCategory = await organizers.createCategory({ name: 'Desserts' });
// Work with tags
const tags = await organizers.getAllTags({ orderBy: 'name' });
const newTag = await organizers.createTag({ name: 'Vegetarian' });
// Work with tools
const tools = await organizers.getAllTools({ page: 1, perPage: 10 });
const newTool = await organizers.createTool({ name: 'Food Processor' });
Full Organizers API documentation
CommentsService
The CommentsService
provides functionality for managing recipe comments, including CRUD operations and filtering:
Comment Operations
getAllComments(params?)
: Get all comments with optional filtering and paginationcreateComment(data)
: Create a new comment for a recipegetComment(commentId)
: Get specific comment by IDupdateComment(commentId, data)
: Update an existing commentdeleteComment(commentId)
: Delete a comment
import { CommentsService } from 'node-mealie';
const comments = new CommentsService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
// Get all comments with filtering
const allComments = await comments.getAllComments({
page: 1,
perPage: 20,
orderBy: 'createdAt',
orderDirection: 'desc',
queryFilter: 'delicious'
});
// Create a new comment
const newComment = await comments.createComment({
recipeId: 'recipe-uuid',
text: 'This recipe is amazing!'
});
// Update a comment
const updatedComment = await comments.updateComment(newComment.id, {
id: newComment.id,
text: 'Updated: This recipe is even better with extra cheese!'
});
// Delete a comment
await comments.deleteComment(newComment.id);
Full Comments API documentation
IngredientParserService
The IngredientParserService
provides functionality for parsing natural language ingredient descriptions into structured data components:
Parser Operations
parseIngredient(ingredient, acceptLanguage?)
: Parse a single ingredient stringparseIngredients(ingredients, acceptLanguage?)
: Parse multiple ingredient strings in bulk
import { IngredientParserService } from 'node-mealie';
const parser = new IngredientParserService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
// Parse a single ingredient
const result = await parser.parseIngredient('2 cups all-purpose flour');
console.log(result.quantity); // 2
console.log(result.unit); // "cups"
console.log(result.food); // "all-purpose flour"
// Parse multiple ingredients
const results = await parser.parseIngredients([
'2 cups all-purpose flour',
'1 tsp vanilla extract',
'3 large eggs, room temperature'
]);
// Parse with localization
const frenchResult = await parser.parseIngredient('2 tasses de farine', 'fr-FR');
Full Ingredient Parser API documentation
FoodsService
The FoodsService
provides functionality for managing food items, including CRUD operations, merging, and filtering:
Food Operations
getAllFoods(params?)
: Get all foods with optional filtering and paginationcreateFood(data)
: Create a new food itemgetOne(itemId)
: Get specific food by IDupdateFood(itemId, data)
: Update an existing food itemdeleteFood(itemId)
: Delete a food itemmergeFoods(data)
: Merge two food items into one
import { FoodsService } from 'node-mealie';
const foods = new FoodsService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
// Get all foods with filtering
const allFoods = await foods.getAllFoods({
search: 'tomato',
orderBy: 'name',
orderDirection: 'asc',
page: 1,
perPage: 50
});
// Create a new food
const newFood = await foods.createFood({ name: 'Cherry Tomatoes' });
// Update a food
const updatedFood = await foods.updateFood(newFood.id, {
name: 'Roma Tomatoes'
});
// Merge foods
await foods.mergeFoods({
fromFood: 'food-123',
toFood: 'food-456'
});
// Delete a food
await foods.deleteFood(newFood.id);
AdminService
The AdminService
provides functionality for system administration tasks, requiring administrator privileges:
Application Management
getAppInfo(acceptLanguage?)
: Get detailed application informationgetAppStatistics(acceptLanguage?)
: Get usage statisticscheckAppConfig(acceptLanguage?)
: Check configuration status
User Management
getAllUsers(options?)
: Get paginated list of userscreateUser(data, acceptLanguage?)
: Create new user accountgetUser(userId, acceptLanguage?)
: Get specific user detailsupdateUser(userId, data, acceptLanguage?)
: Update userdeleteUser(userId, acceptLanguage?)
: Delete userunlockUsers(force?, acceptLanguage?)
: Unlock user accountsgeneratePasswordResetToken(data, acceptLanguage?)
: Generate password reset
Household Management
getAllHouseholds(options?)
: Get paginated list of householdscreateHousehold(data, acceptLanguage?)
: Create new householdgetHousehold(householdId, acceptLanguage?)
: Get specific householdupdateHousehold(householdId, data, acceptLanguage?)
: Update householddeleteHousehold(householdId, acceptLanguage?)
: Delete household
Group Management
getAllGroups(options?)
: Get paginated list of groupscreateGroup(data, acceptLanguage?)
: Create new groupgetGroup(groupId, acceptLanguage?)
: Get specific groupupdateGroup(groupId, data, acceptLanguage?)
: Update groupdeleteGroup(groupId, acceptLanguage?)
: Delete group
Backup Management
getAllBackups(acceptLanguage?)
: List all backupscreateBackup(acceptLanguage?)
: Create system backupgetBackupToken(fileName, acceptLanguage?)
: Get backup download tokendeleteBackup(fileName, acceptLanguage?)
: Delete backupuploadBackup(file, acceptLanguage?)
: Upload backup filerestoreBackup(fileName, acceptLanguage?)
: Restore from backup
System Maintenance
getMaintenanceSummary(acceptLanguage?)
: Get maintenance summarygetStorageDetails(acceptLanguage?)
: Get storage detailscleanImages(acceptLanguage?)
: Clean unused imagescleanTemp(acceptLanguage?)
: Clean temporary filescleanRecipeFolders(acceptLanguage?)
: Clean recipe folders
Email & Debug
checkEmailConfig(acceptLanguage?)
: Check email configurationsendTestEmail(data, acceptLanguage?)
: Send test emaildebugOpenAI(file?, acceptLanguage?)
: Debug OpenAI integration
import { AdminService } from 'node-mealie';
const admin = new AdminService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-admin-token'
});
// Get application statistics
const stats = await admin.getAppStatistics();
console.log(`Total recipes: ${stats.totalRecipes}`);
// User management
const users = await admin.getAllUsers({ page: 1, perPage: 10 });
const newUser = await admin.createUser({
username: 'newuser',
fullName: 'New User',
email: 'user@example.com',
password: 'password123'
});
// Create backup
const backup = await admin.createBackup();
console.log('Backup created:', backup.message);
UtilsService
The UtilsService
provides utility functions for file downloads and other utility operations within Mealie:
File Downloads
downloadFile(params?)
: Download a file from the server, optionally with a specific token
import { UtilsService } from 'node-mealie';
const utils = new UtilsService({
baseUrl: 'https://your-mealie-instance.com',
token: 'your-auth-token'
});
// Download a file
const fileBlob = await utils.downloadFile();
// Download with a specific token
const fileBlob = await utils.downloadFile({ token: 'special-token' });
// Save in browser
const url = URL.createObjectURL(fileBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'downloaded-file';
link.click();
URL.revokeObjectURL(url);
// Save in Node.js
import { writeFile } from 'fs/promises';
const buffer = await fileBlob.arrayBuffer();
await writeFile('downloaded-file', Buffer.from(buffer));
ExploreService
The ExploreService
provides functionality for browsing and discovering public content within Mealie groups. This service is designed for unauthenticated access to public content or can be used with authentication for private groups:
Foods & Ingredients
getFoods(groupSlug, params?)
: Browse available foods in a groupgetFood(groupSlug, itemId, acceptLanguage?)
: Get specific food details
Households
getHouseholds(groupSlug, params?)
: Browse households in a groupgetHousehold(groupSlug, householdSlug, acceptLanguage?)
: Get household details
Organization
getCategories(groupSlug, params?)
: Browse recipe categoriesgetCategory(groupSlug, itemId, acceptLanguage?)
: Get category detailsgetTags(groupSlug, params?)
: Browse recipe tagsgetTag(groupSlug, itemId, acceptLanguage?)
: Get tag detailsgetTools(groupSlug, params?)
: Browse cooking toolsgetTool(groupSlug, itemId, acceptLanguage?)
: Get tool details
Cookbooks & Recipes
getCookbooks(groupSlug, params?)
: Browse cookbooksgetCookbook(groupSlug, itemId, acceptLanguage?)
: Get cookbook detailsgetRecipes(groupSlug, params?)
: Search recipes with complex filtersgetRecipe(groupSlug, recipeSlug, acceptLanguage?)
: Get recipe detailsgetRecipeSuggestions(groupSlug, params?)
: Get recipe suggestions based on available ingredients
import { ExploreService } from 'node-mealie';
const explore = new ExploreService({
baseUrl: 'https://your-mealie-instance.com'
// Authentication optional for public content
});
// Browse recipes with filters
const recipes = await explore.getRecipes('public-recipes', {
categories: ['desserts', 'quick-meals'],
tags: ['vegetarian'],
search: 'pasta',
page: 1,
perPage: 20
});
// Get recipe suggestions based on what you have
const suggestions = await explore.getRecipeSuggestions('public-recipes', {
foods: ['tomatoes', 'basil', 'garlic', 'pasta'],
tools: ['pot', 'knife'],
limit: 5,
maxMissingFoods: 2
});
// Browse content in different languages
const frenchCategories = await explore.getCategories('cuisine-francaise', {
acceptLanguage: 'fr-FR'
});
Full Explore API documentation
Configuration Options
interface MealieClientOptions {
baseUrl?: string; // Base URL for the Mealie API
token?: string; // Authentication token
username?: string; // Username for authentication
password?: string; // Password for authentication
debug?: boolean; // Enable debug logging
}
Error Handling
The library throws MealieError
for all API errors:
try {
await client.getAppInfo();
} catch (error) {
if (error instanceof MealieError) {
console.error('Status:', error.statusCode);
console.error('Message:', error.message);
console.error('Response:', error.response);
}
}
Development
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint
npm run lint
License
MIT