commit 3e81d54262eab29a5e49317c4e0a320ef231f2d1 Author: Nicholas Ward Date: Thu Aug 13 15:39:57 2026 -0500 Initial formulation application diff --git a/.gitea/workflows/build-and-push-image.yaml b/.gitea/workflows/build-and-push-image.yaml new file mode 100644 index 0000000..44ee080 --- /dev/null +++ b/.gitea/workflows/build-and-push-image.yaml @@ -0,0 +1,98 @@ +name: Build & Push Astro Site Image + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + build: + name: 'Build & Push Image' + env: + REGISTRY_USERNAME: nicholas + IMAGE_REGISTRY: git.uuard.com + IMAGE_NAME: nicholas/recipe-book + IMAGE_TAG: ${{ github.sha }} + runs-on: shared-ci + steps: + - name: ⬇️ Checkout repo + uses: actions/checkout@v4 + + - name: ⚙️ Setup Node + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + + - name: ✅ Validate recipe data + run: | + python3 -m pip install --user -r requirements-dev.txt + scripts/validate-content + + - name: 🏗️ Build Astro site + run: | + npm ci + npm run build + + - name: 🔐 Gitea Registry Login + uses: docker/login-action@v3 + with: + registry: ${{ env.IMAGE_REGISTRY }} + username: ${{ env.REGISTRY_USERNAME }} + password: ${{ secrets.CD_CD_BUILD_PUSH }} + + - name: 🐋 Build Docker image + run: docker build -t $IMAGE_REGISTRY/$IMAGE_NAME:$IMAGE_TAG . + + - name: 🚀 Push Docker image + run: docker push $IMAGE_REGISTRY/$IMAGE_NAME:$IMAGE_TAG + + - name: 🧹 Prune images + if: always() + run: docker image prune -f + + deploy: + needs: build + runs-on: recipe-book-deploy + env: + IMAGE_TAG: ${{ github.sha }} + steps: + - name: ⬇️ Checkout repo + uses: actions/checkout@v4 + + - name: Install kubectl + env: + KUBECTL_VERSION: v1.36.2 + run: | + set -euo pipefail + curl -fsSLO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" + curl -fsSLO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl.sha256" + printf '%s %s\n' "$(cat kubectl.sha256)" kubectl | sha256sum -c + mkdir -p "$HOME/.local/bin" + install -m 0755 kubectl "$HOME/.local/bin/kubectl" + printf '%s\n' "$HOME/.local/bin" >> "$GITHUB_PATH" + + - name: Configure Kubernetes access + env: + KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }} + run: | + set -euo pipefail + mkdir -p ~/.kube + printf '%s' "$KUBE_CONFIG" | base64 -d > ~/.kube/config + chmod 600 ~/.kube/config + kubectl auth can-i update deployments --namespace nicholas + + - name: Deploy recipe-book + run: | + set -euo pipefail + sed -E -i "s#newTag: [0-9a-f]+#newTag: ${IMAGE_TAG}#" k8s/kustomization.yaml + grep -q "newTag: ${IMAGE_TAG}$" k8s/kustomization.yaml + kubectl apply --kustomize k8s + if ! kubectl rollout status deployment/recipe-book \ + --namespace nicholas --timeout=180s; then + kubectl rollout undo deployment/recipe-book --namespace nicholas + kubectl rollout status deployment/recipe-book \ + --namespace nicholas --timeout=180s + exit 1 + fi diff --git a/.gitea/workflows/sync-knowledge.yml b/.gitea/workflows/sync-knowledge.yml new file mode 100644 index 0000000..a8ab7ce --- /dev/null +++ b/.gitea/workflows/sync-knowledge.yml @@ -0,0 +1,63 @@ +name: Sync Knowledge + +on: + workflow_dispatch: + push: + branches: + - master + paths: + - .gitea/workflows/sync-knowledge.yml + - container/schemas/** + - culinary/** + - scripts/corpus-export + - scripts/validate-content + - requirements-dev.txt + +env: + OIKB_VERSION: 0.4.0 + +jobs: + sync: + runs-on: recipe-book-deploy + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Check configuration + env: + OPEN_WEBUI_URL: ${{ vars.OPEN_WEBUI_URL }} + OPEN_WEBUI_API_KEY: ${{ secrets.KNOWLEDGE_SYNC_OPEN_WEBUI_API_KEY }} + GOURMAND_KB_ID: ${{ vars.GOURMAND_KB_ID }} + run: | + set -euo pipefail + : "${OPEN_WEBUI_URL:?Missing Actions variable OPEN_WEBUI_URL}" + : "${OPEN_WEBUI_API_KEY:?Missing Actions secret KNOWLEDGE_SYNC_OPEN_WEBUI_API_KEY}" + : "${GOURMAND_KB_ID:?Missing Actions variable GOURMAND_KB_ID}" + command -v python3 >/dev/null || + { echo "python3 is required on the Actions runner" >&2; exit 1; } + + - name: Export recipe corpus + run: | + python3 -m pip install --user -r requirements-dev.txt + scripts/validate-content + scripts/corpus-export + + - name: Install official Open WebUI sync client + run: | + set -euo pipefail + python3 -m venv .venv-oikb + . .venv-oikb/bin/activate + pip install "oikb==$OIKB_VERSION" + + - name: Sync knowledge base + env: + OPEN_WEBUI_URL: ${{ vars.OPEN_WEBUI_URL }} + OPEN_WEBUI_API_KEY: ${{ secrets.KNOWLEDGE_SYNC_OPEN_WEBUI_API_KEY }} + GOURMAND_KB_ID: ${{ vars.GOURMAND_KB_ID }} + run: | + set -euo pipefail + . .venv-oikb/bin/activate + oikb sync generated/open-webui/recipes \ + --kb-id "$GOURMAND_KB_ID" \ + --concurrency 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6858d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Node and Astro +/node_modules/ +/dist/ +/.astro/ +/.env +/.env.* +!.env.example + +# All reproducible exports and migration artifacts +/generated/ + +# Python +__pycache__/ +*.py[cod] +/.venv/ +/venv/ + +# Editors and operating systems +/.vscode/ +/.idea/ +.DS_Store +Thumbs.db +*.swp +*~ + +# Logs and test output +*.log +/coverage/ + +# Local UI reference captures +/ui-reference*.html +/ui-reference*_files/ +/ui-reference*.png + +# Local application databases and SQLite sidecars +/var/*.sqlite +/var/*.sqlite-shm +/var/*.sqlite-wal diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dfeee3c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx:alpine + +RUN rm -rf /usr/share/nginx/html/* + +COPY dist /usr/share/nginx/html/ + +EXPOSE 80 diff --git a/README.md b/README.md new file mode 100644 index 0000000..502eae8 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# advanced-food-making + +A recipe collection + +Canonical version 2 culinary data lives in `culinary/` and is defined by the +vendor-neutral schemas in `container/schemas/v2/`. Two independent Astro applications +consume the shared data and libraries; +see [the culinary data model](docs/culinary-data-model.md) for entity boundaries, +density and unit semantics, and USDA provenance. + +## Knowledge Sync + +The Gitea Actions workflow at +`.gitea/workflows/sync-knowledge.yml` exports the recipes as clean +Markdown and synchronizes them to the Gourmand Open WebUI knowledge base. It +runs when recipe content, ingredient data, or the corpus exporter changes on +`master`, and it can also be started manually. + +Configure these Actions variables in this repository: + +```text +OPEN_WEBUI_URL +GOURMAND_KB_ID +``` + +Configure this Actions secret: + +```text +KNOWLEDGE_SYNC_OPEN_WEBUI_API_KEY +``` + +The existing knowledge-sync account and API key may be reused if the account +has permission to manage files in the Gourmand knowledge base. + +To inspect the generated corpus locally, run: + +```bash +scripts/corpus-export +``` + +Validate canonical entities, schema conformance, and cross-references before +building or committing changes: + +```bash +python3 -m pip install --user -r requirements-dev.txt +scripts/validate-content +``` + +To review purchasing products extracted from the sibling `ledger` receipt +archive, run `scripts/receipt-products propose` and open +`/tools/purchasing-review/`. Export the decisions and apply them with: + +```bash +scripts/receipt-products apply ~/Downloads/purchasing-decisions.json +scripts/validate-content +``` + +Build both applications: + +```bash +npm ci +npm run db:reset # initial setup only; do not use over an edited database +npm run build +``` + +The frontend requires Node.js 22.12 or newer. The public cooking site is a fully +static build in `dist/site`; the SQLite-backed management application is a Node +server build in `dist/app`. They share components and culinary calculation code, +but neither artifact contains the other application's routes. The site build +generates a read-only projection from SQLite before Astro renders its pages. + +Run them independently during development: + +```bash +npm run dev:site # http://localhost:4321 +npm run dev:app # http://localhost:4322/app/ +``` + +The generated files are written to `generated/open-webui/recipes/` and are not +committed. + +Search USDA FoodData Central and import a candidate mapping with: + +```bash +USDA_FDC_API_KEY=... scripts/usda-fdc search "all-purpose flour" +USDA_FDC_API_KEY=... scripts/usda-fdc import flour_all_purpose 790018 +``` + +Add `--reviewed` only after confirming that the USDA description matches the +canonical ingredient. An official USDA JSON download can be supplied with +`--dataset` instead. Never commit the API key. diff --git a/astro.app.config.mjs b/astro.app.config.mjs new file mode 100644 index 0000000..a96a686 --- /dev/null +++ b/astro.app.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from "astro/config"; +import preact from "@astrojs/preact"; +import node from "@astrojs/node"; + +export default defineConfig({ + output: "server", + srcDir: "./src/application", + publicDir: "./public", + outDir: "./dist/app", + adapter: node({ mode: "standalone" }), + integrations: [preact()], + vite: { server: { fs: { allow: ["."] } } }, +}); diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..38dcc06 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,14 @@ +import { defineConfig } from "astro/config"; +import preact from "@astrojs/preact"; + +export default defineConfig({ + site: "https://recipes.uuard.com", + output: "static", + srcDir: "./src/site", + publicDir: "./public", + outDir: "./dist/site", + integrations: [preact()], + vite: { + server: { fs: { allow: ["."] } }, + }, +}); diff --git a/config/purchasing-import-decisions.json b/config/purchasing-import-decisions.json new file mode 100644 index 0000000..3baa54a --- /dev/null +++ b/config/purchasing-import-decisions.json @@ -0,0 +1,43 @@ +{ + "decisions": { + "walmart:10452376": "cheddar_cheese", + "walmart:19400150": "parmesan_cheese", + "walmart:10448316": "salt", + "walmart:12512024": "lemon_juice", + "walmart:426222521": "butter_flavored_shortening", + "walmart:10450340": "heavy_cream", + "walmart:10315395": "rice", + "walmart:705601418": "onion_powder", + "walmart:676979470": "garlic_powder", + "walmart:13424766": "chipotle_pepper_adobo", + "walmart:36120978": "mayonnaise", + "walmart:10315545": "mustard_dijon", + "walmart:15716793": "white_chocolate", + "walmart:43236036": "butter", + "walmart:44001602": "ground_beef_73_27_raw", + "walmart:55014398": "garlic", + "walmart:12166183": "bbq_sauce_hickory_smoke", + "walmart:10315054": "butter", + "walmart:10403017": "flour_all_purpose", + "walmart:664106906": "cornstarch", + "walmart:288194636": "semisweet_chocolate_chips", + "walmart:10315278": "corn_syrup_light", + "walmart:10315012": "light_brown_sugar", + "walmart:10415512": "tomato_puree", + "walmart:41592222": "cream_cheese", + "walmart:10452385": "sharp_cheddar_cheese", + "walmart:10415230": "tomato_crushed_in_juice", + "walmart:10415519": "tomato_paste", + "walmart:10450119": "milk", + "walmart:34186943": "cheddar_cheese", + "walmart:10535480": "vinegar_balsamic", + "walmart:10315088": "bread_crumbs", + "walmart:111156738": "italian_sausage", + "walmart:15136790": "ground_beef_73_27_raw", + "walmart:10295081": "tomato_paste", + "walmart:10295176": "tomato_paste", + "walmart:10315402": "parmesan_cheese", + "walmart:10452370": "cheddar_cheese", + "sams_club:0980250647": "sugar" + } +} diff --git a/container/schemas/v2/allergen.schema.json b/container/schemas/v2/allergen.schema.json new file mode 100644 index 0000000..0d6d345 --- /dev/null +++ b/container/schemas/v2/allergen.schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/allergen.schema.json", + "title": "Allergen", + "type": "object", + "required": ["schema_version", "id", "name", "jurisdictions"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "aliases": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }, + "jurisdictions": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true } + } +} diff --git a/container/schemas/v2/collection.schema.json b/container/schemas/v2/collection.schema.json new file mode 100644 index 0000000..5b23227 --- /dev/null +++ b/container/schemas/v2/collection.schema.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/collection.schema.json", + "title": "Menu or recipe collection", + "type": "object", + "required": ["schema_version", "id", "type", "name", "entries"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "type": { "type": "string", "enum": ["menu", "collection"] }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "description": { "type": "string" }, + "entries": { + "type": "array", + "items": { + "type": "object", + "required": ["recipe_id", "order"], + "additionalProperties": false, + "properties": { + "recipe_id": { "$ref": "common.schema.json#/$defs/id" }, + "recipe_revision": { "$ref": "common.schema.json#/$defs/revision" }, + "order": { "type": "integer", "minimum": 1 }, + "servings": { "$ref": "common.schema.json#/$defs/positiveDecimal" }, + "section": { "type": "string" }, + "notes": { "type": "string" } + } + } + } + } +} diff --git a/container/schemas/v2/common.schema.json b/container/schemas/v2/common.schema.json new file mode 100644 index 0000000..768bbeb --- /dev/null +++ b/container/schemas/v2/common.schema.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/common.schema.json", + "title": "Recipe Book common types", + "$defs": { + "id": { + "type": "string", + "pattern": "^[a-z0-9]+(?:_[a-z0-9]+)*$" + }, + "nonEmptyString": { "type": "string", "minLength": 1 }, + "schemaVersion": { "const": 2 }, + "revision": { "type": "integer", "minimum": 1 }, + "date": { "type": "string", "format": "date" }, + "dateTime": { "type": "string", "format": "date-time" }, + "decimal": { "type": "number", "minimum": 0 }, + "positiveDecimal": { "type": "number", "exclusiveMinimum": 0 }, + "localizedText": { + "type": "object", + "required": ["text"], + "additionalProperties": false, + "properties": { + "text": { "$ref": "#/$defs/nonEmptyString" }, + "language": { "type": "string", "pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$" } + } + }, + "amount": { + "type": "object", + "required": ["quantity", "unit_id"], + "additionalProperties": false, + "properties": { + "quantity": { "$ref": "#/$defs/decimal" }, + "unit_id": { "$ref": "#/$defs/id" }, + "quantity_max": { "$ref": "#/$defs/decimal" }, + "display": { "$ref": "#/$defs/nonEmptyString" } + } + }, + "sourceReference": { + "type": "object", + "required": ["source_type", "reviewed"], + "additionalProperties": false, + "properties": { + "source_type": { + "type": "string", + "enum": ["usda_fdc", "manufacturer", "supplier", "publication", "laboratory", "observation", "manual", "calculated"] + }, + "external_id": { "$ref": "#/$defs/nonEmptyString" }, + "url": { "type": "string", "format": "uri" }, + "title": { "$ref": "#/$defs/nonEmptyString" }, + "publisher": { "$ref": "#/$defs/nonEmptyString" }, + "retrieved_at": { "$ref": "#/$defs/date" }, + "effective_at": { "$ref": "#/$defs/date" }, + "reviewed": { "type": "boolean" }, + "reviewed_at": { "$ref": "#/$defs/date" }, + "notes": { "type": "string" } + }, + "allOf": [ + { + "if": { "properties": { "source_type": { "const": "usda_fdc" } }, "required": ["source_type"] }, + "then": { + "required": ["external_id", "title", "retrieved_at"], + "properties": { "external_id": { "pattern": "^[1-9][0-9]*$" } } + } + } + ] + }, + "media": { + "type": "object", + "required": ["type", "uri"], + "additionalProperties": false, + "properties": { + "type": { "type": "string", "enum": ["image", "video", "audio", "document"] }, + "uri": { "$ref": "#/$defs/nonEmptyString" }, + "alt": { "type": "string" }, + "caption": { "type": "string" }, + "credit": { "type": "string" } + } + } + } +} diff --git a/container/schemas/v2/derived-recipe.schema.json b/container/schemas/v2/derived-recipe.schema.json new file mode 100644 index 0000000..c061c1c --- /dev/null +++ b/container/schemas/v2/derived-recipe.schema.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/derived-recipe.schema.json", + "title": "Disposable derived recipe values", + "description": "Calculated output. This document is never canonical culinary or purchasing input.", + "type": "object", + "required": ["schema_version", "recipe_id", "recipe_revision", "calculation_version", "calculated_at", "input_fingerprint"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "recipe_id": { "$ref": "common.schema.json#/$defs/id" }, + "recipe_revision": { "$ref": "common.schema.json#/$defs/revision" }, + "calculation_version": { "type": "integer", "minimum": 1 }, + "calculated_at": { "$ref": "common.schema.json#/$defs/dateTime" }, + "input_fingerprint": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "cost": { + "type": "object", + "required": ["currency", "batch"], + "additionalProperties": false, + "properties": { + "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, + "batch": { "$ref": "common.schema.json#/$defs/decimal" }, + "per_serving": { "$ref": "common.schema.json#/$defs/decimal" }, + "per_100g": { "$ref": "common.schema.json#/$defs/decimal" } + } + }, + "nutrition": { + "type": "object", + "properties": { + "batch": { "type": "object", "additionalProperties": { "type": "number" } }, + "per_serving": { "type": "object", "additionalProperties": { "type": "number" } }, + "per_100g": { "type": "object", "additionalProperties": { "type": "number" } } + }, + "additionalProperties": false + }, + "allergens": { + "type": "array", + "items": { + "type": "object", + "required": ["allergen_id", "presence"], + "additionalProperties": false, + "properties": { + "allergen_id": { "$ref": "common.schema.json#/$defs/id" }, + "presence": { "type": "string", "enum": ["contains", "may_contain", "unknown"] } + } + } + }, + "completeness": { + "type": "object", + "additionalProperties": false, + "properties": { + "nutrition_weight_fraction": { "type": "number", "minimum": 0, "maximum": 1 }, + "cost_weight_fraction": { "type": "number", "minimum": 0, "maximum": 1 } + } + }, + "warnings": { "type": "array", "items": { "type": "string" } } + } +} diff --git a/container/schemas/v2/equipment.schema.json b/container/schemas/v2/equipment.schema.json new file mode 100644 index 0000000..07516c9 --- /dev/null +++ b/container/schemas/v2/equipment.schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/equipment.schema.json", + "title": "Equipment type", + "type": "object", + "required": ["schema_version", "id", "name"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "category": { "$ref": "common.schema.json#/$defs/id" }, + "notes": { "type": "string" } + } +} diff --git a/container/schemas/v2/ingredient.schema.json b/container/schemas/v2/ingredient.schema.json new file mode 100644 index 0000000..1ac80ad --- /dev/null +++ b/container/schemas/v2/ingredient.schema.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/ingredient.schema.json", + "title": "Canonical ingredient", + "type": "object", + "required": ["schema_version", "id", "name", "status", "categories"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "description": { "type": "string" }, + "status": { "type": "string", "enum": ["active", "deprecated", "archived"] }, + "categories": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "tags": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, "uniqueItems": true }, + "aliases": { + "type": "array", + "items": { + "type": "object", + "required": ["name"], + "additionalProperties": false, + "properties": { + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "language": { "type": "string" }, + "region": { "type": "string" }, + "kind": { "type": "string", "enum": ["common", "alternate_spelling", "trade", "search", "merged"] } + } + } + }, + "default_purchase_item_id": { "$ref": "common.schema.json#/$defs/id" }, + "density_measurements": { + "type": "array", + "items": { + "type": "object", + "required": ["id", "mass", "volume", "source"], + "additionalProperties": false, + "properties": { + "id": { "$ref": "common.schema.json#/$defs/id" }, + "mass": { "$ref": "common.schema.json#/$defs/amount" }, + "volume": { "$ref": "common.schema.json#/$defs/amount" }, + "temperature_c": { "type": "number" }, + "state": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "source": { "$ref": "common.schema.json#/$defs/sourceReference" } + } + } + }, + "measure_conversions": { + "description": "Ingredient-specific measures such as a packed cup or one clove; these are not universal unit conversions.", + "type": "array", + "items": { + "type": "object", + "required": ["id", "from", "to", "source"], + "additionalProperties": false, + "properties": { + "id": { "$ref": "common.schema.json#/$defs/id" }, + "from": { "$ref": "common.schema.json#/$defs/amount" }, + "to": { "$ref": "common.schema.json#/$defs/amount" }, + "state": { "type": "string" }, + "source": { "$ref": "common.schema.json#/$defs/sourceReference" } + } + } + }, + "prep_actions": { + "type": "array", + "items": { + "type": "object", + "required": ["action_id", "yield_factor"], + "additionalProperties": false, + "properties": { + "action_id": { "$ref": "common.schema.json#/$defs/id" }, + "yield_factor": { "description": "Prepared output divided by raw input; may exceed 1 when hydration or cooking adds mass.", "type": "number", "exclusiveMinimum": 0 }, + "notes": { "type": "string" } + } + } + }, + "nutrition_mapping_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "allergen_mapping_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "notes": { "type": "array", "items": { "type": "string" } }, + "extensions": { "type": "object", "additionalProperties": true } + } +} diff --git a/container/schemas/v2/prep-action.schema.json b/container/schemas/v2/prep-action.schema.json new file mode 100644 index 0000000..3c0704c --- /dev/null +++ b/container/schemas/v2/prep-action.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/prep-action.schema.json", + "title": "Preparation action", + "type": "object", + "required": ["schema_version", "id", "name", "action_type"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "action_type": { "type": "string", "enum": ["trim", "peel", "cut", "grind", "drain", "cook", "cool", "other"] }, + "default_yield_factor": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 }, + "notes": { "type": "string" } + } +} diff --git a/container/schemas/v2/purchase-item.schema.json b/container/schemas/v2/purchase-item.schema.json new file mode 100644 index 0000000..02a800b --- /dev/null +++ b/container/schemas/v2/purchase-item.schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/purchase-item.schema.json", + "title": "Purchasing item and price observations", + "type": "object", + "required": ["schema_version", "id", "ingredient_id", "name", "package", "prices", "status"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "ingredient_id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "brand": { "type": "string" }, + "supplier_id": { "$ref": "common.schema.json#/$defs/id" }, + "supplier_sku": { "type": "string" }, + "gtin_upc": { "type": "string" }, + "status": { "type": "string", "enum": ["active", "discontinued", "unavailable"] }, + "package": { + "type": "object", + "required": ["quantity", "unit_id"], + "additionalProperties": false, + "properties": { + "quantity": { "$ref": "common.schema.json#/$defs/positiveDecimal" }, + "unit_id": { "$ref": "common.schema.json#/$defs/id" }, + "units_per_case": { "type": "integer", "minimum": 1 }, + "usable_yield_factor": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 } + } + }, + "prices": { + "type": "array", + "items": { + "type": "object", + "required": ["amount", "currency", "effective_at", "source"], + "additionalProperties": false, + "properties": { + "amount": { "$ref": "common.schema.json#/$defs/decimal" }, + "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, + "effective_at": { "$ref": "common.schema.json#/$defs/date" }, + "expires_at": { "$ref": "common.schema.json#/$defs/date" }, + "source": { "$ref": "common.schema.json#/$defs/sourceReference" } + } + } + }, + "nutrition_mapping_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "allergen_mapping_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true } + } +} diff --git a/container/schemas/v2/recipe.schema.json b/container/schemas/v2/recipe.schema.json new file mode 100644 index 0000000..a90a177 --- /dev/null +++ b/container/schemas/v2/recipe.schema.json @@ -0,0 +1,143 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/recipe.schema.json", + "title": "Canonical recipe", + "type": "object", + "required": ["schema_version", "id", "revision", "status", "title", "yield", "components", "steps", "categories", "tags"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "revision": { "$ref": "common.schema.json#/$defs/revision" }, + "status": { "type": "string", "enum": ["draft", "testing", "active", "retired", "archived"] }, + "title": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "summary": { "type": "string" }, + "categories": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, "uniqueItems": true }, + "tags": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, "uniqueItems": true }, + "yield": { + "type": "object", + "required": ["amount"], + "additionalProperties": false, + "properties": { + "amount": { "$ref": "common.schema.json#/$defs/amount" }, + "servings": { "$ref": "common.schema.json#/$defs/positiveDecimal" }, + "serving_size": { "$ref": "common.schema.json#/$defs/amount" }, + "description": { "type": "string" }, + "yield_factor": { "type": "number", "exclusiveMinimum": 0 }, + "basis": { "type": "string", "enum": ["measured", "estimated", "theoretical"] } + } + }, + "scaling": { + "type": "object", + "required": ["mode"], + "additionalProperties": false, + "properties": { + "mode": { "type": "string", "enum": ["amount", "percentage", "hybrid"] }, + "basis_id": { "$ref": "common.schema.json#/$defs/id" }, + "basis_amount": { "$ref": "common.schema.json#/$defs/amount" } + } + }, + "components": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["id", "name", "items"], + "additionalProperties": false, + "properties": { + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "yield": { "$ref": "common.schema.json#/$defs/amount" }, + "items": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#/$defs/componentItem" } + }, + "notes": { "type": "array", "items": { "type": "string" } } + } + } + }, + "steps": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["id", "order", "instruction"], + "additionalProperties": false, + "properties": { + "id": { "$ref": "common.schema.json#/$defs/id" }, + "order": { "type": "integer", "minimum": 1 }, + "instruction": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "component_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "item_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "equipment_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "duration": { "$ref": "common.schema.json#/$defs/amount" }, + "temperature": { "$ref": "common.schema.json#/$defs/amount" }, + "critical_control_point": { "type": "boolean" } + } + } + }, + "equipment_ids": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/id" }, "uniqueItems": true }, + "shelf_life": { + "type": "object", + "required": ["duration"], + "additionalProperties": false, + "properties": { + "duration": { "$ref": "common.schema.json#/$defs/amount" }, + "storage_condition": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "notes": { "type": "string" } + } + }, + "media": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/media" } }, + "notes": { "type": "array", "items": { "type": "string" } }, + "extensions": { "type": "object", "additionalProperties": true } + }, + "$defs": { + "componentItem": { + "type": "object", + "required": ["id", "reference", "amount"], + "additionalProperties": false, + "properties": { + "id": { "$ref": "common.schema.json#/$defs/id" }, + "reference": { + "oneOf": [ + { + "type": "object", + "required": ["ingredient_id"], + "additionalProperties": false, + "properties": { "ingredient_id": { "$ref": "common.schema.json#/$defs/id" } } + }, + { + "type": "object", + "required": ["recipe_id"], + "additionalProperties": false, + "properties": { + "recipe_id": { "$ref": "common.schema.json#/$defs/id" }, + "revision": { "$ref": "common.schema.json#/$defs/revision" }, + "component_id": { "$ref": "common.schema.json#/$defs/id" } + } + } + ] + }, + "amount": { "$ref": "common.schema.json#/$defs/amount" }, + "percentage": { "type": "number", "minimum": 0 }, + "basis_member": { "type": "boolean" }, + "prep": { + "type": "array", + "items": { + "type": "object", + "required": ["action_id"], + "additionalProperties": false, + "properties": { + "action_id": { "$ref": "common.schema.json#/$defs/id" }, + "yield_factor": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 }, + "notes": { "type": "string" } + } + } + }, + "optional": { "type": "boolean", "default": false }, + "notes": { "type": "string" } + } + } + } +} diff --git a/container/schemas/v2/source-mapping.schema.json b/container/schemas/v2/source-mapping.schema.json new file mode 100644 index 0000000..5c662cb --- /dev/null +++ b/container/schemas/v2/source-mapping.schema.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/source-mapping.schema.json", + "title": "Nutrition or allergen source mapping", + "type": "object", + "required": ["schema_version", "id", "subject", "mapping_type", "source", "status"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "subject": { + "type": "object", + "required": ["type", "id"], + "additionalProperties": false, + "properties": { + "type": { "type": "string", "enum": ["ingredient", "purchase_item", "recipe"] }, + "id": { "$ref": "common.schema.json#/$defs/id" } + } + }, + "mapping_type": { "type": "string", "enum": ["nutrition", "allergen"] }, + "status": { "type": "string", "enum": ["candidate", "reviewed", "rejected", "superseded"] }, + "source": { "$ref": "common.schema.json#/$defs/sourceReference" }, + "usda": { + "type": "object", + "required": ["fdc_id", "data_type", "description"], + "additionalProperties": false, + "properties": { + "fdc_id": { "type": "integer", "minimum": 1 }, + "data_type": { "type": "string", "enum": ["Foundation", "SR Legacy", "FNDDS", "Branded", "Experimental"] }, + "description": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "brand_owner": { "type": "string" }, + "gtin_upc": { "type": "string" } + } + }, + "nutrition_per_100g": { + "type": "object", + "additionalProperties": { "type": ["number", "null"], "minimum": 0 }, + "propertyNames": { "pattern": "^[a-z][a-z0-9_]*_(?:g|mg|mcg|kcal|kj)$" } + }, + "allergens": { + "type": "array", + "items": { + "type": "object", + "required": ["allergen_id", "presence"], + "additionalProperties": false, + "properties": { + "allergen_id": { "$ref": "common.schema.json#/$defs/id" }, + "presence": { "type": "string", "enum": ["contains", "may_contain", "free_from", "unknown"] } + } + } + } + }, + "allOf": [ + { + "if": { "properties": { "source": { "properties": { "source_type": { "const": "usda_fdc" } } } } }, + "then": { "required": ["usda"] } + }, + { + "if": { "properties": { "mapping_type": { "const": "nutrition" } } }, + "then": { "required": ["nutrition_per_100g"] }, + "else": { "required": ["allergens"] } + } + ] +} diff --git a/container/schemas/v2/supplier.schema.json b/container/schemas/v2/supplier.schema.json new file mode 100644 index 0000000..8c7fd07 --- /dev/null +++ b/container/schemas/v2/supplier.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/supplier.schema.json", + "title": "Supplier", + "type": "object", + "required": ["schema_version", "id", "name", "status"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "status": { "type": "string", "enum": ["active", "inactive"] }, + "website": { "type": "string", "format": "uri" }, + "notes": { "type": "array", "items": { "type": "string" } } + } +} diff --git a/container/schemas/v2/unit.schema.json b/container/schemas/v2/unit.schema.json new file mode 100644 index 0000000..40e2b31 --- /dev/null +++ b/container/schemas/v2/unit.schema.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://recipes.uuard.com/schemas/v2/unit.schema.json", + "title": "Normalized unit", + "type": "object", + "required": ["schema_version", "id", "name", "symbol", "dimension", "system"], + "additionalProperties": false, + "properties": { + "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, + "id": { "$ref": "common.schema.json#/$defs/id" }, + "name": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "symbol": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, + "aliases": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, "uniqueItems": true }, + "dimension": { "type": "string", "enum": ["mass", "volume", "count", "temperature", "time", "length"] }, + "system": { "type": "string", "enum": ["metric", "us_customary", "imperial", "universal"] }, + "base_conversion": { + "type": "object", + "required": ["base_unit_id", "factor"], + "additionalProperties": false, + "properties": { + "base_unit_id": { "$ref": "common.schema.json#/$defs/id" }, + "factor": { "$ref": "common.schema.json#/$defs/positiveDecimal" }, + "offset": { "type": "number", "default": 0 } + } + } + } +} diff --git a/culinary/README.md b/culinary/README.md new file mode 100644 index 0000000..12a615b --- /dev/null +++ b/culinary/README.md @@ -0,0 +1,14 @@ +# Canonical culinary data + +This directory contains portable, presentation-neutral schema-version 2 data. +Astro reads these records at build time, but its pages and components are not +canonical culinary storage. + +The records in this directory are the sole canonical culinary source. Do not +create an ingredient for a prepared component when it can be represented as a +recipe reference. + +Directories correspond to entity types and, later, relational tables. Objects +that are edited as one aggregate (recipe components, lines, and steps) remain +embedded in a recipe document. Independently reusable facts use stable IDs and +normalized references. diff --git a/culinary/equipment/blender.yaml b/culinary/equipment/blender.yaml new file mode 100644 index 0000000..9a3a2e0 --- /dev/null +++ b/culinary/equipment/blender.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: blender +name: Blender +category: powered diff --git a/culinary/equipment/food_processor.yaml b/culinary/equipment/food_processor.yaml new file mode 100644 index 0000000..19766c6 --- /dev/null +++ b/culinary/equipment/food_processor.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: food_processor +name: Food processor +category: powered diff --git a/culinary/equipment/griddle.yaml b/culinary/equipment/griddle.yaml new file mode 100644 index 0000000..7364761 --- /dev/null +++ b/culinary/equipment/griddle.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: griddle +name: Griddle +category: cooking diff --git a/culinary/equipment/kitchen_scale.yaml b/culinary/equipment/kitchen_scale.yaml new file mode 100644 index 0000000..bf00d74 --- /dev/null +++ b/culinary/equipment/kitchen_scale.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: kitchen_scale +name: Kitchen scale +category: measuring diff --git a/culinary/equipment/mixing_bowl.yaml b/culinary/equipment/mixing_bowl.yaml new file mode 100644 index 0000000..794cbc2 --- /dev/null +++ b/culinary/equipment/mixing_bowl.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: mixing_bowl +name: Mixing bowl +category: preparation diff --git a/culinary/equipment/oven.yaml b/culinary/equipment/oven.yaml new file mode 100644 index 0000000..2a3b97f --- /dev/null +++ b/culinary/equipment/oven.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: oven +name: Oven +category: cooking diff --git a/culinary/equipment/saucepan.yaml b/culinary/equipment/saucepan.yaml new file mode 100644 index 0000000..06e0fca --- /dev/null +++ b/culinary/equipment/saucepan.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: saucepan +name: Saucepan +category: cooking diff --git a/culinary/equipment/sheet_pan.yaml b/culinary/equipment/sheet_pan.yaml new file mode 100644 index 0000000..fa58bb0 --- /dev/null +++ b/culinary/equipment/sheet_pan.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: sheet_pan +name: Sheet pan +category: bakeware diff --git a/culinary/equipment/skillet.yaml b/culinary/equipment/skillet.yaml new file mode 100644 index 0000000..23cbfd2 --- /dev/null +++ b/culinary/equipment/skillet.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: skillet +name: Skillet +category: cooking diff --git a/culinary/equipment/stand_mixer.yaml b/culinary/equipment/stand_mixer.yaml new file mode 100644 index 0000000..fb586b3 --- /dev/null +++ b/culinary/equipment/stand_mixer.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: stand_mixer +name: Stand mixer +category: powered diff --git a/culinary/equipment/stockpot.yaml b/culinary/equipment/stockpot.yaml new file mode 100644 index 0000000..fce18de --- /dev/null +++ b/culinary/equipment/stockpot.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: stockpot +name: Stockpot +category: cooking diff --git a/culinary/equipment/thermometer.yaml b/culinary/equipment/thermometer.yaml new file mode 100644 index 0000000..a0c4d8c --- /dev/null +++ b/culinary/equipment/thermometer.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: thermometer +name: Thermometer +category: measuring diff --git a/culinary/equipment/whisk.yaml b/culinary/equipment/whisk.yaml new file mode 100644 index 0000000..efcc4cd --- /dev/null +++ b/culinary/equipment/whisk.yaml @@ -0,0 +1,4 @@ +schema_version: 2 +id: whisk +name: Whisk +category: utensil diff --git a/culinary/ingredients/agar.yaml b/culinary/ingredients/agar.yaml new file mode 100644 index 0000000..b1ef278 --- /dev/null +++ b/culinary/ingredients/agar.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: agar +name: Seaweed, agar, dried +status: active +categories: +- unknown +aliases: +- name: agar + kind: search +nutrition_mapping_ids: +- usda_fdc_agar_170090 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/allspice.yaml b/culinary/ingredients/allspice.yaml new file mode 100644 index 0000000..646aa2e --- /dev/null +++ b/culinary/ingredients/allspice.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: allspice +name: Spices, allspice, ground +status: active +categories: +- flavoring +aliases: +- name: allspice + kind: search +nutrition_mapping_ids: +- usda_fdc_allspice_171315 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171315_88417 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171315' + url: https://fdc.nal.usda.gov/food-details/171315/measures + title: Spices, allspice, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88417. + reviewed_at: '2026-08-12' +- id: usda_171315_88418 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171315' + url: https://fdc.nal.usda.gov/food-details/171315/measures + title: Spices, allspice, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88418. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/almond_extract.yaml b/culinary/ingredients/almond_extract.yaml new file mode 100644 index 0000000..0bec887 --- /dev/null +++ b/culinary/ingredients/almond_extract.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: almond_extract +name: almond extract +status: active +categories: +- flavoring +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/apricot_jam.yaml b/culinary/ingredients/apricot_jam.yaml new file mode 100644 index 0000000..92f130f --- /dev/null +++ b/culinary/ingredients/apricot_jam.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: apricot_jam +name: Jams and preserves, apricot +status: active +categories: +- unknown +aliases: +- name: apricot jam + kind: search +nutrition_mapping_ids: +- usda_fdc_apricot_jam_170645 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170645_87021 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 20.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170645' + url: https://fdc.nal.usda.gov/food-details/170645/measures + title: Jams and preserves, apricot + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87021. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/ascorbic_acid.yaml b/culinary/ingredients/ascorbic_acid.yaml new file mode 100644 index 0000000..7d0b57c --- /dev/null +++ b/culinary/ingredients/ascorbic_acid.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: ascorbic_acid +name: ascorbic acid +status: active +categories: +- acid +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/avocado.yaml b/culinary/ingredients/avocado.yaml new file mode 100644 index 0000000..77c513d --- /dev/null +++ b/culinary/ingredients/avocado.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: avocado +name: Avocado, Hass, peeled, raw +status: active +categories: +- produce +aliases: +- name: avocado + kind: search +nutrition_mapping_ids: +- usda_fdc_avocado_2710824 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/bacon.yaml b/culinary/ingredients/bacon.yaml new file mode 100644 index 0000000..539170f --- /dev/null +++ b/culinary/ingredients/bacon.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: bacon +name: Pork, cured, bacon, unprepared +status: active +categories: +- meat +aliases: +- name: regular salted pork bacon + kind: common +- name: bacon, pork, cured, raw + kind: search +nutrition_mapping_ids: +- usda_fdc_bacon_168277 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/baking_powder.yaml b/culinary/ingredients/baking_powder.yaml new file mode 100644 index 0000000..af56825 --- /dev/null +++ b/culinary/ingredients/baking_powder.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: baking_powder +name: Leavening agents, baking powder, double-acting, sodium aluminum sulfate +status: active +categories: +- leavening +aliases: +- name: baking powder + kind: search +nutrition_mapping_ids: +- usda_fdc_baking_powder_172803 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172803_91438 + from: + quantity: 0.5 + unit_id: teaspoon_us + to: + quantity: 2.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172803' + url: https://fdc.nal.usda.gov/food-details/172803/measures + title: Leavening agents, baking powder, double-acting, sodium aluminum sulfate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 91438. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/baking_soda.yaml b/culinary/ingredients/baking_soda.yaml new file mode 100644 index 0000000..31582ae --- /dev/null +++ b/culinary/ingredients/baking_soda.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: baking_soda +name: Leavening agents, baking soda +status: active +categories: +- leavening +aliases: +- name: baking soda + kind: search +nutrition_mapping_ids: +- usda_fdc_baking_soda_175040 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_175040_95485 + from: + quantity: 0.5 + unit_id: teaspoon_us + to: + quantity: 2.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '175040' + url: https://fdc.nal.usda.gov/food-details/175040/measures + title: Leavening agents, baking soda + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95485. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/banana.yaml b/culinary/ingredients/banana.yaml new file mode 100644 index 0000000..fb24ba3 --- /dev/null +++ b/culinary/ingredients/banana.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: banana +name: Bananas, ripe and slightly ripe, raw +status: active +categories: +- other +aliases: +- name: banana + kind: search +nutrition_mapping_ids: +- usda_fdc_banana_1105314 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/barley_malt_powder.yaml b/culinary/ingredients/barley_malt_powder.yaml new file mode 100644 index 0000000..ba28e97 --- /dev/null +++ b/culinary/ingredients/barley_malt_powder.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: barley_malt_powder +name: BARLEY MALT POWDER +status: active +categories: +- baking +aliases: +- name: malted barley powder + kind: common +nutrition_mapping_ids: +- usda_fdc_barley_malt_powder_2027592 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/barley_malt_syrup.yaml b/culinary/ingredients/barley_malt_syrup.yaml new file mode 100644 index 0000000..0287bdd --- /dev/null +++ b/culinary/ingredients/barley_malt_syrup.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: barley_malt_syrup +name: Syrups, malt +status: active +categories: +- sweetener +aliases: +- name: barley malt syrup + kind: search +nutrition_mapping_ids: +- usda_fdc_barley_malt_syrup_169660 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169660_85302 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 21.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169660' + url: https://fdc.nal.usda.gov/food-details/169660/measures + title: Syrups, malt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85302. + reviewed_at: '2026-08-12' +- id: usda_169660_85301 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 332.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169660' + url: https://fdc.nal.usda.gov/food-details/169660/measures + title: Syrups, malt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85301. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/basil.yaml b/culinary/ingredients/basil.yaml new file mode 100644 index 0000000..b498023 --- /dev/null +++ b/culinary/ingredients/basil.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: basil +name: Spices, basil, dried +status: active +categories: +- unknown +aliases: +- name: basil + kind: search +nutrition_mapping_ids: +- usda_fdc_basil_171317 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171317_88422 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 2.1 + unit_id: gram + state: leaves + source: + source_type: usda_fdc + external_id: '171317' + url: https://fdc.nal.usda.gov/food-details/171317/measures + title: Spices, basil, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88422. + reviewed_at: '2026-08-12' +- id: usda_171317_88421 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 0.7 + unit_id: gram + state: leaves + source: + source_type: usda_fdc + external_id: '171317' + url: https://fdc.nal.usda.gov/food-details/171317/measures + title: Spices, basil, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88421. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/bbq_sauce_hickory_smoke.yaml b/culinary/ingredients/bbq_sauce_hickory_smoke.yaml new file mode 100644 index 0000000..ce52c2b --- /dev/null +++ b/culinary/ingredients/bbq_sauce_hickory_smoke.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: bbq_sauce_hickory_smoke +name: SWEET BABY RAY'S, HICKORY & BROWN SUGAR BARBECUE SAUCE +status: active +categories: +- sauce +aliases: +- name: Sweet Baby Ray's Hickory and Brown Sugar BBQ sauce + kind: common +- name: Sweet Baby Ray's Hickory & Brown Sugar Barbecue Sauce + kind: search +nutrition_mapping_ids: +- usda_fdc_bbq_sauce_hickory_smoke_2020420 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/beef_base.yaml b/culinary/ingredients/beef_base.yaml new file mode 100644 index 0000000..13f6845 --- /dev/null +++ b/culinary/ingredients/beef_base.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: beef_base +name: BEEF BASE, BEEF +status: active +categories: +- seasoning +aliases: +- name: Member's Mark beef soup base + kind: common +- name: Member's Mark Beef Base + kind: search +nutrition_mapping_ids: +- usda_fdc_beef_base_2422131 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/beer.yaml b/culinary/ingredients/beer.yaml new file mode 100644 index 0000000..196c5c3 --- /dev/null +++ b/culinary/ingredients/beer.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: beer +name: Alcoholic beverage, beer, regular, all +status: active +categories: +- unknown +aliases: +- name: beer + kind: search +nutrition_mapping_ids: +- usda_fdc_beer_168746 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168746_83686 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 29.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168746' + url: https://fdc.nal.usda.gov/food-details/168746/measures + title: Alcoholic beverage, beer, regular, all + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83686. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/black_pepper_ground.yaml b/culinary/ingredients/black_pepper_ground.yaml new file mode 100644 index 0000000..b0a8091 --- /dev/null +++ b/culinary/ingredients/black_pepper_ground.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: black_pepper_ground +name: Spices, pepper, black +status: active +categories: +- spice +aliases: +- name: black pepper, ground + kind: search +nutrition_mapping_ids: +- usda_fdc_black_pepper_ground_170931 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170931_87561 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.9 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170931' + url: https://fdc.nal.usda.gov/food-details/170931/measures + title: Spices, pepper, black + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87561. + reviewed_at: '2026-08-12' +- id: usda_170931_87560 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.3 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170931' + url: https://fdc.nal.usda.gov/food-details/170931/measures + title: Spices, pepper, black + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87560. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/blueberry.yaml b/culinary/ingredients/blueberry.yaml new file mode 100644 index 0000000..6bf0a04 --- /dev/null +++ b/culinary/ingredients/blueberry.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: blueberry +name: Blueberries, raw +status: active +categories: +- fruit +aliases: +- name: blueberry + kind: common +- name: blueberries + kind: search +nutrition_mapping_ids: +- usda_fdc_blueberry_2346411 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/bread_crumbs.yaml b/culinary/ingredients/bread_crumbs.yaml new file mode 100644 index 0000000..bfe61ea --- /dev/null +++ b/culinary/ingredients/bread_crumbs.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: bread_crumbs +name: Bread, crumbs, dry, grated, plain +status: active +categories: +- unknown +aliases: +- name: bread crumbs + kind: search +nutrition_mapping_ids: +- usda_fdc_bread_crumbs_174928 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174928_95194 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 108.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174928' + url: https://fdc.nal.usda.gov/food-details/174928/measures + title: Bread, crumbs, dry, grated, plain + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95194. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/brown_sugar.yaml b/culinary/ingredients/brown_sugar.yaml new file mode 100644 index 0000000..0077dad --- /dev/null +++ b/culinary/ingredients/brown_sugar.yaml @@ -0,0 +1,51 @@ +schema_version: 2 +id: brown_sugar +name: Sugars, brown +status: active +categories: +- sweetener +aliases: +- name: brown sugar + kind: search +- name: light brown sugar + kind: search +nutrition_mapping_ids: +- usda_fdc_brown_sugar_168833 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168833_83855 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 220.0 + unit_id: gram + state: packed + source: + source_type: usda_fdc + external_id: '168833' + url: https://fdc.nal.usda.gov/food-details/168833/measures + title: Sugars, brown + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83855. + reviewed_at: '2026-08-12' +- id: usda_168833_83857 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.6 + unit_id: gram + state: packed + source: + source_type: usda_fdc + external_id: '168833' + url: https://fdc.nal.usda.gov/food-details/168833/measures + title: Sugars, brown + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83857. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/butter.yaml b/culinary/ingredients/butter.yaml new file mode 100644 index 0000000..3b6a364 --- /dev/null +++ b/culinary/ingredients/butter.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: butter +name: Butter, stick, unsalted +status: active +categories: +- fat +aliases: +- name: unsalted butter + kind: common +- name: butter, unsalted + kind: search +nutrition_mapping_ids: +- usda_fdc_butter_789828 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/butter_extract.yaml b/culinary/ingredients/butter_extract.yaml new file mode 100644 index 0000000..0f6c5ef --- /dev/null +++ b/culinary/ingredients/butter_extract.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: butter_extract +name: butter extract +status: active +categories: +- flavoring +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/butter_flavored_shortening.yaml b/culinary/ingredients/butter_flavored_shortening.yaml new file mode 100644 index 0000000..ca7cf95 --- /dev/null +++ b/culinary/ingredients/butter_flavored_shortening.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: butter_flavored_shortening +name: Crisco Shortening, All Vegetable, Butter Flavor +status: active +categories: +- fat +aliases: +- name: Crisco butter-flavor shortening + kind: common +- name: Crisco Butter Flavor All-Vegetable Shortening + kind: search +nutrition_mapping_ids: +- usda_fdc_butter_flavored_shortening_2756254 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/buttermilk.yaml b/culinary/ingredients/buttermilk.yaml new file mode 100644 index 0000000..63b62be --- /dev/null +++ b/culinary/ingredients/buttermilk.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: buttermilk +name: Buttermilk, low fat +status: active +categories: +- liquid +aliases: +- name: low-fat buttermilk + kind: common +- name: buttermilk, low-fat + kind: search +nutrition_mapping_ids: +- usda_fdc_buttermilk_2259792 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/buttermilk_powder.yaml b/culinary/ingredients/buttermilk_powder.yaml new file mode 100644 index 0000000..926338d --- /dev/null +++ b/culinary/ingredients/buttermilk_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: buttermilk_powder +name: Milk, buttermilk, dried +status: active +categories: +- liquid +aliases: +- name: buttermilk powder + kind: search +nutrition_mapping_ids: +- usda_fdc_buttermilk_powder_171274 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171274_88339 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 120.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171274' + url: https://fdc.nal.usda.gov/food-details/171274/measures + title: Milk, buttermilk, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88339. + reviewed_at: '2026-08-12' +- id: usda_171274_88340 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171274' + url: https://fdc.nal.usda.gov/food-details/171274/measures + title: Milk, buttermilk, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88340. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/canola_oil.yaml b/culinary/ingredients/canola_oil.yaml new file mode 100644 index 0000000..5f96b8e --- /dev/null +++ b/culinary/ingredients/canola_oil.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: canola_oil +name: Oil, canola +status: active +categories: +- oil +aliases: +- name: rapeseed oil, low erucic acid + kind: common +- name: canola oil + kind: search +nutrition_mapping_ids: +- usda_fdc_canola_oil_748278 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_748278_192340 + from: + quantity: 100.0 + unit_id: milliliter + to: + quantity: 90.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '748278' + url: https://fdc.nal.usda.gov/food-details/748278/measures + title: Oil, canola + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 192340. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cardamom.yaml b/culinary/ingredients/cardamom.yaml new file mode 100644 index 0000000..c49c4d6 --- /dev/null +++ b/culinary/ingredients/cardamom.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: cardamom +name: Spices, cardamom +status: active +categories: +- unknown +aliases: +- name: cardamom + kind: search +nutrition_mapping_ids: +- usda_fdc_cardamom_170919 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170919_87536 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.0 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170919' + url: https://fdc.nal.usda.gov/food-details/170919/measures + title: Spices, cardamom + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87536. + reviewed_at: '2026-08-12' +- id: usda_170919_87537 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.8 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170919' + url: https://fdc.nal.usda.gov/food-details/170919/measures + title: Spices, cardamom + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87537. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/carrot.yaml b/culinary/ingredients/carrot.yaml new file mode 100644 index 0000000..f8eb571 --- /dev/null +++ b/culinary/ingredients/carrot.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: carrot +name: Carrots, mature, raw +status: active +categories: +- unknown +aliases: +- name: carrot + kind: search +nutrition_mapping_ids: +- usda_fdc_carrot_2258586 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/cayenne.yaml b/culinary/ingredients/cayenne.yaml new file mode 100644 index 0000000..f18c00f --- /dev/null +++ b/culinary/ingredients/cayenne.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: cayenne +name: Spices, pepper, red or cayenne +status: active +categories: +- unknown +aliases: +- name: cayenne + kind: search +nutrition_mapping_ids: +- usda_fdc_cayenne_170932 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170932_87565 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170932' + url: https://fdc.nal.usda.gov/food-details/170932/measures + title: Spices, pepper, red or cayenne + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87565. + reviewed_at: '2026-08-12' +- id: usda_170932_87564 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170932' + url: https://fdc.nal.usda.gov/food-details/170932/measures + title: Spices, pepper, red or cayenne + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87564. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cheddar_cheese.yaml b/culinary/ingredients/cheddar_cheese.yaml new file mode 100644 index 0000000..45bb056 --- /dev/null +++ b/culinary/ingredients/cheddar_cheese.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: cheddar_cheese +name: Cheese, cheddar +status: active +categories: +- unknown +aliases: +- name: cheddar cheese + kind: search +nutrition_mapping_ids: +- usda_fdc_cheddar_cheese_328637 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/chicken_base.yaml b/culinary/ingredients/chicken_base.yaml new file mode 100644 index 0000000..68e5d64 --- /dev/null +++ b/culinary/ingredients/chicken_base.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: chicken_base +name: CHICKEN BASE +status: active +categories: +- seasoning +aliases: +- name: Member's Mark chicken soup base + kind: common +- name: Member's Mark Chicken Base + kind: search +nutrition_mapping_ids: +- usda_fdc_chicken_base_1948045 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/chicken_breast.yaml b/culinary/ingredients/chicken_breast.yaml new file mode 100644 index 0000000..442f121 --- /dev/null +++ b/culinary/ingredients/chicken_breast.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: chicken_breast +name: Chicken, breast, boneless, skinless, raw +status: active +categories: +- unknown +aliases: +- name: boneless skinless chicken breast + kind: common +- name: chicken breast, boneless skinless, raw + kind: search +nutrition_mapping_ids: +- usda_fdc_chicken_breast_2646170 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/chili_crisp.yaml b/culinary/ingredients/chili_crisp.yaml new file mode 100644 index 0000000..6610699 --- /dev/null +++ b/culinary/ingredients/chili_crisp.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: chili_crisp +name: chili crisp, generic +status: active +categories: +- condiment +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/chili_powder.yaml b/culinary/ingredients/chili_powder.yaml new file mode 100644 index 0000000..a1df25a --- /dev/null +++ b/culinary/ingredients/chili_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: chili_powder +name: Spices, chili powder +status: active +categories: +- spice +aliases: +- name: chili powder + kind: search +nutrition_mapping_ids: +- usda_fdc_chili_powder_171319 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171319_88428 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 8.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171319' + url: https://fdc.nal.usda.gov/food-details/171319/measures + title: Spices, chili powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88428. + reviewed_at: '2026-08-12' +- id: usda_171319_88427 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171319' + url: https://fdc.nal.usda.gov/food-details/171319/measures + title: Spices, chili powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88427. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/chipotle_pepper_adobo.yaml b/culinary/ingredients/chipotle_pepper_adobo.yaml new file mode 100644 index 0000000..e8363d3 --- /dev/null +++ b/culinary/ingredients/chipotle_pepper_adobo.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: chipotle_pepper_adobo +name: CHIPOTLES PEPPERS IN ADOBO SAUCE, CHIPOTLES PEPPERS IN ADOBO +status: active +categories: +- unknown +aliases: +- name: canned chipotles in adobo + kind: common +- name: "La Coste\xF1a chipotle peppers in adobo sauce" + kind: search +nutrition_mapping_ids: +- usda_fdc_chipotle_pepper_adobo_2420526 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/chipotle_pepper_sauce_tobasco.yaml b/culinary/ingredients/chipotle_pepper_sauce_tobasco.yaml new file mode 100644 index 0000000..ba92a52 --- /dev/null +++ b/culinary/ingredients/chipotle_pepper_sauce_tobasco.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: chipotle_pepper_sauce_tobasco +name: Sauce, ready-to-serve, pepper, TABASCO +status: active +categories: +- unknown +aliases: +- name: chipotle pepper sauce, tobasco + kind: search +nutrition_mapping_ids: +- usda_fdc_chipotle_pepper_sauce_tobasco_174528 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174528_94522 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174528' + url: https://fdc.nal.usda.gov/food-details/174528/measures + title: Sauce, ready-to-serve, pepper, TABASCO + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94522. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/chipotle_powder.yaml b/culinary/ingredients/chipotle_powder.yaml new file mode 100644 index 0000000..e9baee5 --- /dev/null +++ b/culinary/ingredients/chipotle_powder.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: chipotle_powder +name: GROUND CHIPOTLE CHILE +status: active +categories: +- spice +aliases: +- name: chipotle powder + kind: search +nutrition_mapping_ids: +- usda_fdc_chipotle_powder_2545016 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/cilantro.yaml b/culinary/ingredients/cilantro.yaml new file mode 100644 index 0000000..7100fa6 --- /dev/null +++ b/culinary/ingredients/cilantro.yaml @@ -0,0 +1,36 @@ +schema_version: 2 +id: cilantro +name: Coriander (cilantro) leaves, raw +status: active +categories: +- produce +aliases: +- name: cilantro + kind: common +- name: fresh coriander leaves + kind: common +- name: cilantro, fresh + kind: search +- name: cilantro, chopped + kind: search +nutrition_mapping_ids: +- usda_fdc_cilantro_169997 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169997_85844 + from: + quantity: 0.25 + unit_id: cup_us + to: + quantity: 4.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169997' + url: https://fdc.nal.usda.gov/food-details/169997/measures + title: Coriander (cilantro) leaves, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85844. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cinnamon.yaml b/culinary/ingredients/cinnamon.yaml new file mode 100644 index 0000000..a4c688a --- /dev/null +++ b/culinary/ingredients/cinnamon.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: cinnamon +name: Spices, cinnamon, ground +status: active +categories: +- flavoring +aliases: +- name: cinnamon + kind: search +nutrition_mapping_ids: +- usda_fdc_cinnamon_171320 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171320_88429 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171320' + url: https://fdc.nal.usda.gov/food-details/171320/measures + title: Spices, cinnamon, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88429. + reviewed_at: '2026-08-12' +- id: usda_171320_88430 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 7.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171320' + url: https://fdc.nal.usda.gov/food-details/171320/measures + title: Spices, cinnamon, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88430. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/citric_acid.yaml b/culinary/ingredients/citric_acid.yaml new file mode 100644 index 0000000..6b21bf5 --- /dev/null +++ b/culinary/ingredients/citric_acid.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: citric_acid +name: citric acid +status: active +categories: +- other +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/cloves.yaml b/culinary/ingredients/cloves.yaml new file mode 100644 index 0000000..7275539 --- /dev/null +++ b/culinary/ingredients/cloves.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: cloves +name: Spices, cloves, ground +status: active +categories: +- other +aliases: +- name: clove + kind: common +- name: cloves + kind: search +nutrition_mapping_ids: +- usda_fdc_cloves_171321 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171321_88431 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.1 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171321' + url: https://fdc.nal.usda.gov/food-details/171321/measures + title: Spices, cloves, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88431. + reviewed_at: '2026-08-12' +- id: usda_171321_88432 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171321' + url: https://fdc.nal.usda.gov/food-details/171321/measures + title: Spices, cloves, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88432. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cocoa_powder.yaml b/culinary/ingredients/cocoa_powder.yaml new file mode 100644 index 0000000..1a4c2df --- /dev/null +++ b/culinary/ingredients/cocoa_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: cocoa_powder +name: Cocoa, dry powder, unsweetened +status: active +categories: +- other +aliases: +- name: cocoa powder + kind: search +nutrition_mapping_ids: +- usda_fdc_cocoa_powder_169593 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169593_85187 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.4 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169593' + url: https://fdc.nal.usda.gov/food-details/169593/measures + title: Cocoa, dry powder, unsweetened + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85187. + reviewed_at: '2026-08-12' +- id: usda_169593_85186 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 86.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169593' + url: https://fdc.nal.usda.gov/food-details/169593/measures + title: Cocoa, dry powder, unsweetened + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85186. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/coconut_milk.yaml b/culinary/ingredients/coconut_milk.yaml new file mode 100644 index 0000000..15fa5de --- /dev/null +++ b/culinary/ingredients/coconut_milk.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: coconut_milk +name: Nuts, coconut milk, canned (liquid expressed from grated meat and water) +status: active +categories: +- unknown +aliases: +- name: canned coconut milk + kind: common +- name: coconut milk, canned + kind: search +nutrition_mapping_ids: +- usda_fdc_coconut_milk_170173 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170173_86171 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 226.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170173' + url: https://fdc.nal.usda.gov/food-details/170173/measures + title: Nuts, coconut milk, canned (liquid expressed from grated meat and water) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86171. + reviewed_at: '2026-08-12' +- id: usda_170173_86172 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 15.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170173' + url: https://fdc.nal.usda.gov/food-details/170173/measures + title: Nuts, coconut milk, canned (liquid expressed from grated meat and water) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86172. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/confectioners_sugar.yaml b/culinary/ingredients/confectioners_sugar.yaml new file mode 100644 index 0000000..5828b49 --- /dev/null +++ b/culinary/ingredients/confectioners_sugar.yaml @@ -0,0 +1,66 @@ +schema_version: 2 +id: confectioners_sugar +name: Sugars, powdered +status: active +categories: +- unknown +aliases: +- name: confectioners' sugar + kind: search +nutrition_mapping_ids: +- usda_fdc_confectioners_sugar_169656 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169656_85291 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 100.0 + unit_id: gram + state: sifted + source: + source_type: usda_fdc + external_id: '169656' + url: https://fdc.nal.usda.gov/food-details/169656/measures + title: Sugars, powdered + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85291. + reviewed_at: '2026-08-12' +- id: usda_169656_85293 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169656' + url: https://fdc.nal.usda.gov/food-details/169656/measures + title: Sugars, powdered + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85293. + reviewed_at: '2026-08-12' +- id: usda_169656_85292 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 8.0 + unit_id: gram + state: unsifted + source: + source_type: usda_fdc + external_id: '169656' + url: https://fdc.nal.usda.gov/food-details/169656/measures + title: Sugars, powdered + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85292. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cooked_pinto_beans_drained.yaml b/culinary/ingredients/cooked_pinto_beans_drained.yaml new file mode 100644 index 0000000..36dad69 --- /dev/null +++ b/culinary/ingredients/cooked_pinto_beans_drained.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: cooked_pinto_beans_drained +name: Beans, pinto, mature seeds, cooked, boiled, without salt +status: active +categories: +- unknown +aliases: +- name: home-cooked pinto beans + kind: common +- name: pinto beans, cooked from dry, drained + kind: search +nutrition_mapping_ids: +- usda_fdc_cooked_pinto_beans_drained_175200 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_175200_95833 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 10.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '175200' + url: https://fdc.nal.usda.gov/food-details/175200/measures + title: Beans, pinto, mature seeds, cooked, boiled, without salt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95833. + reviewed_at: '2026-08-12' +- id: usda_175200_95832 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 171.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '175200' + url: https://fdc.nal.usda.gov/food-details/175200/measures + title: Beans, pinto, mature seeds, cooked, boiled, without salt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95832. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/coriander.yaml b/culinary/ingredients/coriander.yaml new file mode 100644 index 0000000..986907e --- /dev/null +++ b/culinary/ingredients/coriander.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: coriander +name: Spices, coriander seed +status: active +categories: +- unknown +aliases: +- name: coriander + kind: search +nutrition_mapping_ids: +- usda_fdc_coriander_170922 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170922_87543 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170922' + url: https://fdc.nal.usda.gov/food-details/170922/measures + title: Spices, coriander seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87543. + reviewed_at: '2026-08-12' +- id: usda_170922_87542 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170922' + url: https://fdc.nal.usda.gov/food-details/170922/measures + title: Spices, coriander seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87542. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/corn_syrup_light.yaml b/culinary/ingredients/corn_syrup_light.yaml new file mode 100644 index 0000000..f8c2b51 --- /dev/null +++ b/culinary/ingredients/corn_syrup_light.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: corn_syrup_light +name: Syrups, corn, light +status: active +categories: +- unknown +aliases: +- name: corn syrup, light + kind: search +nutrition_mapping_ids: +- usda_fdc_corn_syrup_light_168837 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168837_83865 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 22.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168837' + url: https://fdc.nal.usda.gov/food-details/168837/measures + title: Syrups, corn, light + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83865. + reviewed_at: '2026-08-12' +- id: usda_168837_83864 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 341.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168837' + url: https://fdc.nal.usda.gov/food-details/168837/measures + title: Syrups, corn, light + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83864. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cornstarch.yaml b/culinary/ingredients/cornstarch.yaml new file mode 100644 index 0000000..1ebd938 --- /dev/null +++ b/culinary/ingredients/cornstarch.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: cornstarch +name: Cornstarch +status: active +categories: +- starch +aliases: +- name: corn starch + kind: search +nutrition_mapping_ids: +- usda_fdc_cornstarch_169698 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169698_85370 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 128.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169698' + url: https://fdc.nal.usda.gov/food-details/169698/measures + title: Cornstarch + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85370. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/cream_cheese.yaml b/culinary/ingredients/cream_cheese.yaml new file mode 100644 index 0000000..435242c --- /dev/null +++ b/culinary/ingredients/cream_cheese.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: cream_cheese +name: Cream cheese, full fat, block +status: active +categories: +- liquid +aliases: +- name: cream cheese + kind: search +nutrition_mapping_ids: +- usda_fdc_cream_cheese_2346385 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/cumin.yaml b/culinary/ingredients/cumin.yaml new file mode 100644 index 0000000..54a1ada --- /dev/null +++ b/culinary/ingredients/cumin.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: cumin +name: Spices, cumin seed +status: active +categories: +- spice +aliases: +- name: cumin + kind: search +nutrition_mapping_ids: +- usda_fdc_cumin_170923 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170923_87544 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.1 + unit_id: gram + state: whole + source: + source_type: usda_fdc + external_id: '170923' + url: https://fdc.nal.usda.gov/food-details/170923/measures + title: Spices, cumin seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87544. + reviewed_at: '2026-08-12' +- id: usda_170923_87545 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.0 + unit_id: gram + state: whole + source: + source_type: usda_fdc + external_id: '170923' + url: https://fdc.nal.usda.gov/food-details/170923/measures + title: Spices, cumin seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87545. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/dark_chocolate.yaml b/culinary/ingredients/dark_chocolate.yaml new file mode 100644 index 0000000..bd17928 --- /dev/null +++ b/culinary/ingredients/dark_chocolate.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: dark_chocolate +name: Chocolate, dark, 70-85% cacao solids +status: active +categories: +- inclusion +aliases: +- name: "70\u201385% dark chocolate" + kind: common +- name: "dark chocolate, 70\u201385% cacao" + kind: search +nutrition_mapping_ids: +- usda_fdc_dark_chocolate_170273 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/dark_cocoa_powder.yaml b/culinary/ingredients/dark_cocoa_powder.yaml new file mode 100644 index 0000000..e092392 --- /dev/null +++ b/culinary/ingredients/dark_cocoa_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: dark_cocoa_powder +name: Cocoa, dry powder, unsweetened, processed with alkali +status: active +categories: +- unknown +aliases: +- name: dark cocoa powder + kind: search +nutrition_mapping_ids: +- usda_fdc_dark_cocoa_powder_169594 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169594_85189 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.4 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169594' + url: https://fdc.nal.usda.gov/food-details/169594/measures + title: Cocoa, dry powder, unsweetened, processed with alkali + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85189. + reviewed_at: '2026-08-12' +- id: usda_169594_85188 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 86.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169594' + url: https://fdc.nal.usda.gov/food-details/169594/measures + title: Cocoa, dry powder, unsweetened, processed with alkali + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85188. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/dextrose.yaml b/culinary/ingredients/dextrose.yaml new file mode 100644 index 0000000..aa6d966 --- /dev/null +++ b/culinary/ingredients/dextrose.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: dextrose +name: DEXTROSE PURE AND NATURAL SWEETENER, DEXTROSE +status: active +categories: +- unknown +aliases: +- name: dextrose + kind: search +nutrition_mapping_ids: +- usda_fdc_dextrose_1991846 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/dill.yaml b/culinary/ingredients/dill.yaml new file mode 100644 index 0000000..9c240b4 --- /dev/null +++ b/culinary/ingredients/dill.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: dill +name: Dill weed, fresh +status: active +categories: +- unknown +aliases: +- name: dill + kind: search +nutrition_mapping_ids: +- usda_fdc_dill_172233 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172233_90129 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 8.9 + unit_id: gram + state: sprigs + source: + source_type: usda_fdc + external_id: '172233' + url: https://fdc.nal.usda.gov/food-details/172233/measures + title: Dill weed, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90129. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/dried_chilis.yaml b/culinary/ingredients/dried_chilis.yaml new file mode 100644 index 0000000..f46292a --- /dev/null +++ b/culinary/ingredients/dried_chilis.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: dried_chilis +name: Peppers, hot chile, sun-dried +status: active +categories: +- unknown +aliases: +- name: dried Chinese red chiles + kind: common +- name: dried hot red chiles + kind: search +- name: Tien Tsin chile peppers, dried whole + kind: search +nutrition_mapping_ids: +- usda_fdc_dried_chilis_168570 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168570_83346 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 37.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168570' + url: https://fdc.nal.usda.gov/food-details/168570/measures + title: Peppers, hot chile, sun-dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83346. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/egg_whites.yaml b/culinary/ingredients/egg_whites.yaml new file mode 100644 index 0000000..a5f1380 --- /dev/null +++ b/culinary/ingredients/egg_whites.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: egg_whites +name: Egg, white, raw, fresh +status: active +categories: +- unknown +aliases: +- name: egg whites + kind: search +nutrition_mapping_ids: +- usda_fdc_egg_whites_172183 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172183_90044 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 243.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172183' + url: https://fdc.nal.usda.gov/food-details/172183/measures + title: Egg, white, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90044. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/egg_whole.yaml b/culinary/ingredients/egg_whole.yaml new file mode 100644 index 0000000..5a1feff --- /dev/null +++ b/culinary/ingredients/egg_whole.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: egg_whole +name: Egg, whole, raw, fresh +status: active +categories: +- egg +aliases: +- name: egg, whole + kind: search +nutrition_mapping_ids: +- usda_fdc_egg_whole_171287 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171287_88377 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 243.0 + unit_id: gram + state: (4.86 large eggs) + source: + source_type: usda_fdc + external_id: '171287' + url: https://fdc.nal.usda.gov/food-details/171287/measures + title: Egg, whole, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88377. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/egg_yolk.yaml b/culinary/ingredients/egg_yolk.yaml new file mode 100644 index 0000000..79c07a5 --- /dev/null +++ b/culinary/ingredients/egg_yolk.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: egg_yolk +name: Egg, yolk, raw, fresh +status: active +categories: +- unknown +aliases: +- name: egg yolk + kind: search +nutrition_mapping_ids: +- usda_fdc_egg_yolk_172184 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172184_90046 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 243.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172184' + url: https://fdc.nal.usda.gov/food-details/172184/measures + title: Egg, yolk, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90046. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/espresso_powder.yaml b/culinary/ingredients/espresso_powder.yaml new file mode 100644 index 0000000..83d4736 --- /dev/null +++ b/culinary/ingredients/espresso_powder.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: espresso_powder +name: ESPRESSO INSTANT POWDER, ESPRESSO +status: active +categories: +- other +aliases: +- name: espresso powder + kind: search +nutrition_mapping_ids: +- usda_fdc_espresso_powder_2059824 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/fennel_seed.yaml b/culinary/ingredients/fennel_seed.yaml new file mode 100644 index 0000000..2965efa --- /dev/null +++ b/culinary/ingredients/fennel_seed.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: fennel_seed +name: Spices, fennel seed +status: active +categories: +- unknown +aliases: +- name: fennel seed + kind: search +nutrition_mapping_ids: +- usda_fdc_fennel_seed_171323 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171323_88436 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.8 + unit_id: gram + state: whole + source: + source_type: usda_fdc + external_id: '171323' + url: https://fdc.nal.usda.gov/food-details/171323/measures + title: Spices, fennel seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88436. + reviewed_at: '2026-08-12' +- id: usda_171323_88435 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.0 + unit_id: gram + state: whole + source: + source_type: usda_fdc + external_id: '171323' + url: https://fdc.nal.usda.gov/food-details/171323/measures + title: Spices, fennel seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88435. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/flour_all_purpose.yaml b/culinary/ingredients/flour_all_purpose.yaml new file mode 100644 index 0000000..d01b2be --- /dev/null +++ b/culinary/ingredients/flour_all_purpose.yaml @@ -0,0 +1,17 @@ +schema_version: 2 +id: flour_all_purpose +name: Flour, wheat, all-purpose, unenriched, unbleached +status: active +categories: +- flour +aliases: +- name: plain flour + region: GB + kind: common +- name: all-purpose flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_all_purpose_790018 +allergen_mapping_ids: [] +notes: +- USDA nutrition mapping and ingredient-specific volume measures remain to be reviewed. diff --git a/culinary/ingredients/flour_bread.yaml b/culinary/ingredients/flour_bread.yaml new file mode 100644 index 0000000..0ed6820 --- /dev/null +++ b/culinary/ingredients/flour_bread.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: flour_bread +name: Flour, bread, white, enriched, unbleached +status: active +categories: +- flour +aliases: +- name: bread flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_bread_790146 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/flour_cake.yaml b/culinary/ingredients/flour_cake.yaml new file mode 100644 index 0000000..226db88 --- /dev/null +++ b/culinary/ingredients/flour_cake.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: flour_cake +name: Wheat flour, white, cake, enriched +status: active +categories: +- flour +aliases: +- name: cake flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_cake_169723 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169723_85397 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 137.0 + unit_id: gram + state: unsifted, dipped + source: + source_type: usda_fdc + external_id: '169723' + url: https://fdc.nal.usda.gov/food-details/169723/measures + title: Wheat flour, white, cake, enriched + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85397. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/flour_corn.yaml b/culinary/ingredients/flour_corn.yaml new file mode 100644 index 0000000..a975dfe --- /dev/null +++ b/culinary/ingredients/flour_corn.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: flour_corn +name: Corn flour, masa harina, white or yellow, dry, raw +status: active +categories: +- unknown +aliases: +- name: corn flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_corn_2710835 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/flour_pastry.yaml b/culinary/ingredients/flour_pastry.yaml new file mode 100644 index 0000000..78b75b7 --- /dev/null +++ b/culinary/ingredients/flour_pastry.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: flour_pastry +name: Flour, pastry, unenriched, unbleached +status: active +categories: +- unknown +aliases: +- name: pastry flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_pastry_1104913 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/flour_whole_wheat.yaml b/culinary/ingredients/flour_whole_wheat.yaml new file mode 100644 index 0000000..a2c28a6 --- /dev/null +++ b/culinary/ingredients/flour_whole_wheat.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: flour_whole_wheat +name: Flour, whole wheat, unenriched +status: active +categories: +- flour +aliases: +- name: whole wheat flour + kind: search +nutrition_mapping_ids: +- usda_fdc_flour_whole_wheat_790085 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/garlic.yaml b/culinary/ingredients/garlic.yaml new file mode 100644 index 0000000..46fccb8 --- /dev/null +++ b/culinary/ingredients/garlic.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: garlic +name: Garlic, raw +status: active +categories: +- unknown +aliases: +- name: garlic + kind: search +- name: garlic, minced + kind: search +nutrition_mapping_ids: +- usda_fdc_garlic_1104647 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/garlic_dehydrated_minced.yaml b/culinary/ingredients/garlic_dehydrated_minced.yaml new file mode 100644 index 0000000..ff4881d --- /dev/null +++ b/culinary/ingredients/garlic_dehydrated_minced.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: garlic_dehydrated_minced +name: garlic, dehydrated, minced +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/garlic_powder.yaml b/culinary/ingredients/garlic_powder.yaml new file mode 100644 index 0000000..337e800 --- /dev/null +++ b/culinary/ingredients/garlic_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: garlic_powder +name: Spices, garlic powder +status: active +categories: +- spice +aliases: +- name: garlic powder + kind: search +nutrition_mapping_ids: +- usda_fdc_garlic_powder_171325 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171325_88440 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 9.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171325' + url: https://fdc.nal.usda.gov/food-details/171325/measures + title: Spices, garlic powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88440. + reviewed_at: '2026-08-12' +- id: usda_171325_88439 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 3.1 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171325' + url: https://fdc.nal.usda.gov/food-details/171325/measures + title: Spices, garlic powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88439. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/gelatin.yaml b/culinary/ingredients/gelatin.yaml new file mode 100644 index 0000000..50993b0 --- /dev/null +++ b/culinary/ingredients/gelatin.yaml @@ -0,0 +1,16 @@ +schema_version: 2 +id: gelatin +name: Gelatins, dry powder, unsweetened +status: active +categories: +- unknown +aliases: +- name: gelatin + kind: search +- name: gelatin, granulated + kind: search +- name: granulated gelatin + kind: search +nutrition_mapping_ids: +- usda_fdc_gelatin_169599 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/ginger.yaml b/culinary/ingredients/ginger.yaml new file mode 100644 index 0000000..677a8f3 --- /dev/null +++ b/culinary/ingredients/ginger.yaml @@ -0,0 +1,54 @@ +schema_version: 2 +id: ginger +name: Ginger root, raw +status: active +categories: +- produce +aliases: +- name: ginger root + kind: search +- name: fresh ginger + kind: search +- name: ginger, grated + kind: search +- name: ginger, minced + kind: search +nutrition_mapping_ids: +- usda_fdc_ginger_169231 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169231_84483 + from: + quantity: 0.25 + unit_id: cup_us + to: + quantity: 24.0 + unit_id: gram + state: slices (1" dia) + source: + source_type: usda_fdc + external_id: '169231' + url: https://fdc.nal.usda.gov/food-details/169231/measures + title: Ginger root, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 84483. + reviewed_at: '2026-08-12' +- id: usda_169231_84482 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169231' + url: https://fdc.nal.usda.gov/food-details/169231/measures + title: Ginger root, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 84482. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/ginger_ground.yaml b/culinary/ingredients/ginger_ground.yaml new file mode 100644 index 0000000..efdd3fb --- /dev/null +++ b/culinary/ingredients/ginger_ground.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: ginger_ground +name: Spices, ginger, ground +status: active +categories: +- other +aliases: +- name: ground ginger + kind: search +nutrition_mapping_ids: +- usda_fdc_ginger_ground_170926 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170926_87551 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.2 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170926' + url: https://fdc.nal.usda.gov/food-details/170926/measures + title: Spices, ginger, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87551. + reviewed_at: '2026-08-12' +- id: usda_170926_87550 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170926' + url: https://fdc.nal.usda.gov/food-details/170926/measures + title: Spices, ginger, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87550. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/glucose.yaml b/culinary/ingredients/glucose.yaml new file mode 100644 index 0000000..6d5b087 --- /dev/null +++ b/culinary/ingredients/glucose.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: glucose +name: GLUCOSE +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: +- usda_fdc_glucose_1983545 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/graham_cracker.yaml b/culinary/ingredients/graham_cracker.yaml new file mode 100644 index 0000000..e79a675 --- /dev/null +++ b/culinary/ingredients/graham_cracker.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: graham_cracker +name: Cookies, graham crackers, plain or honey (includes cinnamon) +status: active +categories: +- unknown +aliases: +- name: graham cracker + kind: common +- name: graham cracker crumbs + kind: common +- name: graham crackers, plain or honey, crushed + kind: search +nutrition_mapping_ids: +- usda_fdc_graham_cracker_174957 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174957_95263 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 84.0 + unit_id: gram + state: crushed + source: + source_type: usda_fdc + external_id: '174957' + url: https://fdc.nal.usda.gov/food-details/174957/measures + title: Cookies, graham crackers, plain or honey (includes cinnamon) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95263. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/green_onion.yaml b/culinary/ingredients/green_onion.yaml new file mode 100644 index 0000000..bb96ff8 --- /dev/null +++ b/culinary/ingredients/green_onion.yaml @@ -0,0 +1,16 @@ +schema_version: 2 +id: green_onion +name: Green onion, (scallion), bulb and greens, root removed, raw +status: active +categories: +- unknown +aliases: +- name: green onion + kind: search +- name: scallion + kind: search +- name: scallion, minced + kind: search +nutrition_mapping_ids: +- usda_fdc_green_onion_2727585 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/ground_beef_73_27_raw.yaml b/culinary/ingredients/ground_beef_73_27_raw.yaml new file mode 100644 index 0000000..c7ee917 --- /dev/null +++ b/culinary/ingredients/ground_beef_73_27_raw.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: ground_beef_73_27_raw +name: 73% LEAN 27% FAT GROUND BEEF +status: active +categories: +- meat +aliases: +- name: 73/27 ground beef, raw + kind: search +nutrition_mapping_ids: +- usda_fdc_ground_beef_73_27_raw_2450404 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/heavy_cream.yaml b/culinary/ingredients/heavy_cream.yaml new file mode 100644 index 0000000..39ef54f --- /dev/null +++ b/culinary/ingredients/heavy_cream.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: heavy_cream +name: Cream, heavy +status: active +categories: +- liquid +aliases: +- name: heavy cream + kind: search +nutrition_mapping_ids: +- usda_fdc_heavy_cream_2346386 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/hidden_valley_ranch_dry_seasoning.yaml b/culinary/ingredients/hidden_valley_ranch_dry_seasoning.yaml new file mode 100644 index 0000000..07c60df --- /dev/null +++ b/culinary/ingredients/hidden_valley_ranch_dry_seasoning.yaml @@ -0,0 +1,18 @@ +schema_version: 2 +id: hidden_valley_ranch_dry_seasoning +name: RANCH SEASONING & SALAD DRESSING MIX, RANCH +status: active +categories: +- seasoning +aliases: +- name: Hidden Valley dry ranch + kind: trade +- name: ranch powder + kind: common +- name: ranch seasoning + kind: common +- name: Hidden Valley Original Ranch dry seasoning mix + kind: search +nutrition_mapping_ids: +- usda_fdc_hidden_valley_ranch_dry_seasoning_2546792 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/honey.yaml b/culinary/ingredients/honey.yaml new file mode 100644 index 0000000..fe29476 --- /dev/null +++ b/culinary/ingredients/honey.yaml @@ -0,0 +1,45 @@ +schema_version: 2 +id: honey +name: Honey +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: +- usda_fdc_honey_169640 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169640_85264 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 339.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169640' + url: https://fdc.nal.usda.gov/food-details/169640/measures + title: Honey + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85264. + reviewed_at: '2026-08-12' +- id: usda_169640_85265 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 21.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169640' + url: https://fdc.nal.usda.gov/food-details/169640/measures + title: Honey + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85265. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/hot_cherry_peppers.yaml b/culinary/ingredients/hot_cherry_peppers.yaml new file mode 100644 index 0000000..eadcdc8 --- /dev/null +++ b/culinary/ingredients/hot_cherry_peppers.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: hot_cherry_peppers +name: Peppers, hot pickled, canned +status: active +categories: +- unknown +aliases: +- name: hot cherry peppers + kind: search +nutrition_mapping_ids: +- usda_fdc_hot_cherry_peppers_169766 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169766_85471 + from: + quantity: 0.25 + unit_id: cup_us + to: + quantity: 34.0 + unit_id: gram + state: drained + source: + source_type: usda_fdc + external_id: '169766' + url: https://fdc.nal.usda.gov/food-details/169766/measures + title: Peppers, hot pickled, canned + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85471. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/hot_pepper_juice.yaml b/culinary/ingredients/hot_pepper_juice.yaml new file mode 100644 index 0000000..5903991 --- /dev/null +++ b/culinary/ingredients/hot_pepper_juice.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: hot_pepper_juice +name: hot pepper juice +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/hot_sauce.yaml b/culinary/ingredients/hot_sauce.yaml new file mode 100644 index 0000000..af3aa0f --- /dev/null +++ b/culinary/ingredients/hot_sauce.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: hot_sauce +name: Sauce, ready-to-serve, pepper or hot +status: active +categories: +- unknown +aliases: +- name: hot sauce + kind: search +nutrition_mapping_ids: +- usda_fdc_hot_sauce_174527 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174527_94521 + from: + quantity: 0.25 + unit_id: teaspoon_us + to: + quantity: 1.2 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174527' + url: https://fdc.nal.usda.gov/food-details/174527/measures + title: Sauce, ready-to-serve, pepper or hot + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94521. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/imitation_crab.yaml b/culinary/ingredients/imitation_crab.yaml new file mode 100644 index 0000000..4a6a503 --- /dev/null +++ b/culinary/ingredients/imitation_crab.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: imitation_crab +name: Crustaceans, crab, alaska king, imitation, made from surimi +status: active +categories: +- unknown +aliases: +- name: imitation crab + kind: common +- name: imitation crab, minced + kind: search +nutrition_mapping_ids: +- usda_fdc_imitation_crab_174203 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/instant_yeast.yaml b/culinary/ingredients/instant_yeast.yaml new file mode 100644 index 0000000..b008c71 --- /dev/null +++ b/culinary/ingredients/instant_yeast.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: instant_yeast +name: Leavening agents, yeast, baker's, active dry +status: active +categories: +- leavening +aliases: +- name: commercial instant dry yeast + kind: common +- name: instant yeast + kind: search +nutrition_mapping_ids: +- usda_fdc_instant_yeast_175043 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_175043_95490 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 12.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '175043' + url: https://fdc.nal.usda.gov/food-details/175043/measures + title: Leavening agents, yeast, baker's, active dry + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95490. + reviewed_at: '2026-08-12' +- id: usda_175043_95489 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '175043' + url: https://fdc.nal.usda.gov/food-details/175043/measures + title: Leavening agents, yeast, baker's, active dry + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 95489. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/italian_sausage.yaml b/culinary/ingredients/italian_sausage.yaml new file mode 100644 index 0000000..400ac15 --- /dev/null +++ b/culinary/ingredients/italian_sausage.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: italian_sausage +name: Sausage, Italian, pork, mild, raw +status: active +categories: +- meat +aliases: +- name: Italian sausage + kind: search +nutrition_mapping_ids: +- usda_fdc_italian_sausage_171631 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/jalapeno_peppers_pickled.yaml b/culinary/ingredients/jalapeno_peppers_pickled.yaml new file mode 100644 index 0000000..b0ea036 --- /dev/null +++ b/culinary/ingredients/jalapeno_peppers_pickled.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: jalapeno_peppers_pickled +name: Peppers, jalapeno, canned, solids and liquids +status: active +categories: +- unknown +aliases: +- name: jalapeno peppers, pickled + kind: search +- name: jalapeno, diced + kind: search +- name: jalapeno, pickled, diced + kind: search +nutrition_mapping_ids: +- usda_fdc_jalapeno_peppers_pickled_170080 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170080_86011 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 104.0 + unit_id: gram + state: sliced + source: + source_type: usda_fdc + external_id: '170080' + url: https://fdc.nal.usda.gov/food-details/170080/measures + title: Peppers, jalapeno, canned, solids and liquids + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86011. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/ketchup.yaml b/culinary/ingredients/ketchup.yaml new file mode 100644 index 0000000..1964efe --- /dev/null +++ b/culinary/ingredients/ketchup.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: ketchup +name: Catsup +status: active +categories: +- condiment +aliases: +- name: ketchup + kind: search +nutrition_mapping_ids: +- usda_fdc_ketchup_168556 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168556_83301 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 17.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168556' + url: https://fdc.nal.usda.gov/food-details/168556/measures + title: Catsup + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83301. + reviewed_at: '2026-08-12' +- id: usda_168556_83303 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 240.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168556' + url: https://fdc.nal.usda.gov/food-details/168556/measures + title: Catsup + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83303. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/lactic_acid_88.yaml b/culinary/ingredients/lactic_acid_88.yaml new file mode 100644 index 0000000..b535274 --- /dev/null +++ b/culinary/ingredients/lactic_acid_88.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: lactic_acid_88 +name: lactic acid 88% +status: active +categories: +- other +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/lard.yaml b/culinary/ingredients/lard.yaml new file mode 100644 index 0000000..1075c49 --- /dev/null +++ b/culinary/ingredients/lard.yaml @@ -0,0 +1,45 @@ +schema_version: 2 +id: lard +name: Lard +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: +- usda_fdc_lard_171401 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171401_88638 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 12.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171401' + url: https://fdc.nal.usda.gov/food-details/171401/measures + title: Lard + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88638. + reviewed_at: '2026-08-12' +- id: usda_171401_88639 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 205.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171401' + url: https://fdc.nal.usda.gov/food-details/171401/measures + title: Lard + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88639. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/lecithin.yaml b/culinary/ingredients/lecithin.yaml new file mode 100644 index 0000000..42b1e98 --- /dev/null +++ b/culinary/ingredients/lecithin.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: lecithin +name: Oil, soybean lecithin +status: active +categories: +- other +aliases: +- name: lecithin + kind: search +nutrition_mapping_ids: +- usda_fdc_lecithin_171426 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171426_88700 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 13.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171426' + url: https://fdc.nal.usda.gov/food-details/171426/measures + title: Oil, soybean lecithin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88700. + reviewed_at: '2026-08-12' +- id: usda_171426_88701 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 218.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171426' + url: https://fdc.nal.usda.gov/food-details/171426/measures + title: Oil, soybean lecithin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88701. + reviewed_at: '2026-08-12' +- id: usda_171426_88702 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171426' + url: https://fdc.nal.usda.gov/food-details/171426/measures + title: Oil, soybean lecithin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88702. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/lecithin_liquid_soy.yaml b/culinary/ingredients/lecithin_liquid_soy.yaml new file mode 100644 index 0000000..363290d --- /dev/null +++ b/culinary/ingredients/lecithin_liquid_soy.yaml @@ -0,0 +1,11 @@ +schema_version: 2 +id: lecithin_liquid_soy +name: lecithin, liquid soy +status: active +categories: +- unknown +aliases: +- name: liquid soy lecithin + kind: common +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/lecithin_powder.yaml b/culinary/ingredients/lecithin_powder.yaml new file mode 100644 index 0000000..f611bc4 --- /dev/null +++ b/culinary/ingredients/lecithin_powder.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: lecithin_powder +name: BOB'S RED MILL, SOY LECITHIN GRANULES +status: active +categories: +- other +aliases: +- name: lecithin powder + kind: search +nutrition_mapping_ids: +- usda_fdc_lecithin_powder_2125978 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/lemon_juice.yaml b/culinary/ingredients/lemon_juice.yaml new file mode 100644 index 0000000..0f5f22c --- /dev/null +++ b/culinary/ingredients/lemon_juice.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: lemon_juice +name: Lemon juice, raw +status: active +categories: +- other +aliases: +- name: lemon juice + kind: search +nutrition_mapping_ids: +- usda_fdc_lemon_juice_167747 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_167747_81887 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 244.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '167747' + url: https://fdc.nal.usda.gov/food-details/167747/measures + title: Lemon juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81887. + reviewed_at: '2026-08-12' +- id: usda_167747_81888 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 30.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '167747' + url: https://fdc.nal.usda.gov/food-details/167747/measures + title: Lemon juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81888. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/lemon_zest.yaml b/culinary/ingredients/lemon_zest.yaml new file mode 100644 index 0000000..b8b9217 --- /dev/null +++ b/culinary/ingredients/lemon_zest.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: lemon_zest +name: Lemon peel, raw +status: active +categories: +- unknown +aliases: +- name: lemon zest + kind: search +nutrition_mapping_ids: +- usda_fdc_lemon_zest_167749 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_167749_81896 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '167749' + url: https://fdc.nal.usda.gov/food-details/167749/measures + title: Lemon peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81896. + reviewed_at: '2026-08-12' +- id: usda_167749_81895 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '167749' + url: https://fdc.nal.usda.gov/food-details/167749/measures + title: Lemon peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81895. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/lime_juice.yaml b/culinary/ingredients/lime_juice.yaml new file mode 100644 index 0000000..b70730d --- /dev/null +++ b/culinary/ingredients/lime_juice.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: lime_juice +name: Lime juice, raw +status: active +categories: +- acid +aliases: +- name: lime juice + kind: search +nutrition_mapping_ids: +- usda_fdc_lime_juice_168156 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168156_82572 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 242.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168156' + url: https://fdc.nal.usda.gov/food-details/168156/measures + title: Lime juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 82572. + reviewed_at: '2026-08-12' +- id: usda_168156_82573 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 30.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168156' + url: https://fdc.nal.usda.gov/food-details/168156/measures + title: Lime juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 82573. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/liquid_sunflower_lecithin.yaml b/culinary/ingredients/liquid_sunflower_lecithin.yaml new file mode 100644 index 0000000..e9f05a3 --- /dev/null +++ b/culinary/ingredients/liquid_sunflower_lecithin.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: liquid_sunflower_lecithin +name: LIQUID SUNFLOWER LECITHIN +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: +- usda_fdc_liquid_sunflower_lecithin_2373459 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/mace_nutmeg.yaml b/culinary/ingredients/mace_nutmeg.yaml new file mode 100644 index 0000000..a460462 --- /dev/null +++ b/culinary/ingredients/mace_nutmeg.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: mace_nutmeg +name: Spices, mace, ground +status: active +categories: +- other +aliases: +- name: mace/nutmeg + kind: search +nutrition_mapping_ids: +- usda_fdc_mace_nutmeg_170927 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170927_87553 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170927' + url: https://fdc.nal.usda.gov/food-details/170927/measures + title: Spices, mace, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87553. + reviewed_at: '2026-08-12' +- id: usda_170927_87552 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170927' + url: https://fdc.nal.usda.gov/food-details/170927/measures + title: Spices, mace, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87552. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/maple_extract.yaml b/culinary/ingredients/maple_extract.yaml new file mode 100644 index 0000000..59ddbbe --- /dev/null +++ b/culinary/ingredients/maple_extract.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: maple_extract +name: maple extract +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/marjoram.yaml b/culinary/ingredients/marjoram.yaml new file mode 100644 index 0000000..74a3765 --- /dev/null +++ b/culinary/ingredients/marjoram.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: marjoram +name: Spices, marjoram, dried +status: active +categories: +- herb +aliases: +- name: marjoram + kind: search +nutrition_mapping_ids: +- usda_fdc_marjoram_170928 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170928_87555 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 1.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170928' + url: https://fdc.nal.usda.gov/food-details/170928/measures + title: Spices, marjoram, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87555. + reviewed_at: '2026-08-12' +- id: usda_170928_87554 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 0.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170928' + url: https://fdc.nal.usda.gov/food-details/170928/measures + title: Spices, marjoram, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87554. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/mayonnaise.yaml b/culinary/ingredients/mayonnaise.yaml new file mode 100644 index 0000000..da11441 --- /dev/null +++ b/culinary/ingredients/mayonnaise.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: mayonnaise +name: Salad dressing, mayonnaise, regular +status: active +categories: +- condiment +aliases: +- name: mayonnaise + kind: search +nutrition_mapping_ids: +- usda_fdc_mayonnaise_171009 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171009_87758 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 13.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171009' + url: https://fdc.nal.usda.gov/food-details/171009/measures + title: Salad dressing, mayonnaise, regular + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87758. + reviewed_at: '2026-08-12' +- id: usda_171009_87759 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 220.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171009' + url: https://fdc.nal.usda.gov/food-details/171009/measures + title: Salad dressing, mayonnaise, regular + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87759. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/michiu_wine.yaml b/culinary/ingredients/michiu_wine.yaml new file mode 100644 index 0000000..c0d4933 --- /dev/null +++ b/culinary/ingredients/michiu_wine.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: michiu_wine +name: COOKING RICE WINE +status: active +categories: +- alcohol +aliases: +- name: michiu wine + kind: search +nutrition_mapping_ids: +- usda_fdc_michiu_wine_468381 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/milk.yaml b/culinary/ingredients/milk.yaml new file mode 100644 index 0000000..4a967a0 --- /dev/null +++ b/culinary/ingredients/milk.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: milk +name: Milk, reduced fat, fluid, 2% milkfat, with added vitamin A and vitamin D +status: active +categories: +- liquid +aliases: +- name: 2% milk + kind: common +- name: milk, 2% reduced-fat + kind: search +nutrition_mapping_ids: +- usda_fdc_milk_746778 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/milk_powder_whole.yaml b/culinary/ingredients/milk_powder_whole.yaml new file mode 100644 index 0000000..5b69b7b --- /dev/null +++ b/culinary/ingredients/milk_powder_whole.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: milk_powder_whole +name: DRY WHOLE POWDERED MILK +status: active +categories: +- unknown +aliases: +- name: milk powder, whole + kind: search +nutrition_mapping_ids: +- usda_fdc_milk_powder_whole_2491279 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/mint_dried.yaml b/culinary/ingredients/mint_dried.yaml new file mode 100644 index 0000000..1bc2ff2 --- /dev/null +++ b/culinary/ingredients/mint_dried.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: mint_dried +name: Spearmint, dried +status: active +categories: +- herb +aliases: +- name: dried spearmint + kind: common +- name: mint, dried + kind: search +nutrition_mapping_ids: +- usda_fdc_mint_dried_172239 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172239_90140 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 0.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172239' + url: https://fdc.nal.usda.gov/food-details/172239/measures + title: Spearmint, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90140. + reviewed_at: '2026-08-12' +- id: usda_172239_90141 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 1.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172239' + url: https://fdc.nal.usda.gov/food-details/172239/measures + title: Spearmint, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90141. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/molasses.yaml b/culinary/ingredients/molasses.yaml new file mode 100644 index 0000000..e6494bf --- /dev/null +++ b/culinary/ingredients/molasses.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: molasses +name: Molasses +status: active +categories: +- sweetener +aliases: [] +nutrition_mapping_ids: +- usda_fdc_molasses_168820 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168820_83829 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 337.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168820' + url: https://fdc.nal.usda.gov/food-details/168820/measures + title: Molasses + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83829. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/monterey_jack_cheese.yaml b/culinary/ingredients/monterey_jack_cheese.yaml new file mode 100644 index 0000000..71bfb65 --- /dev/null +++ b/culinary/ingredients/monterey_jack_cheese.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: monterey_jack_cheese +name: Cheese, monterey jack, solid +status: active +categories: +- unknown +aliases: +- name: monterey jack cheese + kind: search +nutrition_mapping_ids: +- usda_fdc_monterey_jack_cheese_2647438 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/mozzarella_cheese.yaml b/culinary/ingredients/mozzarella_cheese.yaml new file mode 100644 index 0000000..78fff90 --- /dev/null +++ b/culinary/ingredients/mozzarella_cheese.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: mozzarella_cheese +name: Cheese, mozzarella, low moisture, part-skim +status: active +categories: +- unknown +aliases: +- name: low-moisture part-skim mozzarella + kind: common +- name: mozzarella cheese, low-moisture part-skim + kind: search +nutrition_mapping_ids: +- usda_fdc_mozzarella_cheese_329370 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/msg.yaml b/culinary/ingredients/msg.yaml new file mode 100644 index 0000000..9fc2b75 --- /dev/null +++ b/culinary/ingredients/msg.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: msg +name: MSG MONOSODIUM GLUTAMATE +status: active +categories: +- seasoning +aliases: +- name: msg + kind: search +nutrition_mapping_ids: +- usda_fdc_msg_2449440 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/mustard_dijon.yaml b/culinary/ingredients/mustard_dijon.yaml new file mode 100644 index 0000000..aa7b461 --- /dev/null +++ b/culinary/ingredients/mustard_dijon.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: mustard_dijon +name: DIJON MUSTARD +status: active +categories: +- condiment +aliases: +- name: Dijon mustard, generic + kind: search +nutrition_mapping_ids: +- usda_fdc_mustard_dijon_2029577 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/mustard_yellow.yaml b/culinary/ingredients/mustard_yellow.yaml new file mode 100644 index 0000000..68b068c --- /dev/null +++ b/culinary/ingredients/mustard_yellow.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: mustard_yellow +name: Mustard, prepared, yellow +status: active +categories: +- condiment +aliases: +- name: yellow mustard + kind: search +- name: mustard + kind: search +nutrition_mapping_ids: +- usda_fdc_mustard_yellow_326698 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/nonfat_milk_powder.yaml b/culinary/ingredients/nonfat_milk_powder.yaml new file mode 100644 index 0000000..68027cf --- /dev/null +++ b/culinary/ingredients/nonfat_milk_powder.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: nonfat_milk_powder +name: Milk, dry, nonfat, calcium reduced +status: active +categories: +- liquid +aliases: +- name: nonfat milk powder + kind: search +nutrition_mapping_ids: +- usda_fdc_nonfat_milk_powder_171273 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/nutmeg.yaml b/culinary/ingredients/nutmeg.yaml new file mode 100644 index 0000000..489a4d1 --- /dev/null +++ b/culinary/ingredients/nutmeg.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: nutmeg +name: Spices, nutmeg, ground +status: active +categories: +- other +aliases: +- name: nutmeg + kind: search +nutrition_mapping_ids: +- usda_fdc_nutmeg_171326 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171326_88442 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 7.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171326' + url: https://fdc.nal.usda.gov/food-details/171326/measures + title: Spices, nutmeg, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88442. + reviewed_at: '2026-08-12' +- id: usda_171326_88441 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.2 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171326' + url: https://fdc.nal.usda.gov/food-details/171326/measures + title: Spices, nutmeg, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88441. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/oats.yaml b/culinary/ingredients/oats.yaml new file mode 100644 index 0000000..ef6a503 --- /dev/null +++ b/culinary/ingredients/oats.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: oats +name: Oats, whole grain, rolled, old fashioned +status: active +categories: +- inclusion +aliases: +- name: oats + kind: search +nutrition_mapping_ids: +- usda_fdc_oats_2346396 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/olive_oil.yaml b/culinary/ingredients/olive_oil.yaml new file mode 100644 index 0000000..2c34e15 --- /dev/null +++ b/culinary/ingredients/olive_oil.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: olive_oil +name: Oil, olive, extra virgin +status: active +categories: +- unknown +aliases: +- name: EVOO + kind: common +- name: extra-virgin olive oil + kind: search +nutrition_mapping_ids: +- usda_fdc_olive_oil_748608 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_748608_192355 + from: + quantity: 100.0 + unit_id: milliliter + to: + quantity: 90.7 + unit_id: gram + source: + source_type: usda_fdc + external_id: '748608' + url: https://fdc.nal.usda.gov/food-details/748608/measures + title: Oil, olive, extra virgin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 192355. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/onion_dehydrated_flake.yaml b/culinary/ingredients/onion_dehydrated_flake.yaml new file mode 100644 index 0000000..1ea44fe --- /dev/null +++ b/culinary/ingredients/onion_dehydrated_flake.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: onion_dehydrated_flake +name: Onions, dehydrated flakes +status: active +categories: +- unknown +aliases: +- name: onion dehydrated flake + kind: search +nutrition_mapping_ids: +- usda_fdc_onion_dehydrated_flake_170002 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170002_85873 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170002' + url: https://fdc.nal.usda.gov/food-details/170002/measures + title: Onions, dehydrated flakes + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85873. + reviewed_at: '2026-08-12' +- id: usda_170002_85874 + from: + quantity: 0.25 + unit_id: cup_us + to: + quantity: 14.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170002' + url: https://fdc.nal.usda.gov/food-details/170002/measures + title: Onions, dehydrated flakes + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85874. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/onion_dehydrated_powder.yaml b/culinary/ingredients/onion_dehydrated_powder.yaml new file mode 100644 index 0000000..13e7163 --- /dev/null +++ b/culinary/ingredients/onion_dehydrated_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: onion_dehydrated_powder +name: Spices, onion powder +status: active +categories: +- unknown +aliases: +- name: onion, dehydrated, powder + kind: search +nutrition_mapping_ids: +- usda_fdc_onion_dehydrated_powder_171327 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171327_88444 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/measures + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88444. + reviewed_at: '2026-08-12' +- id: usda_171327_88443 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.4 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/measures + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88443. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/onion_powder.yaml b/culinary/ingredients/onion_powder.yaml new file mode 100644 index 0000000..85db2ef --- /dev/null +++ b/culinary/ingredients/onion_powder.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: onion_powder +name: Spices, onion powder +status: active +categories: +- spice +aliases: +- name: onion powder + kind: search +nutrition_mapping_ids: +- usda_fdc_onion_powder_171327 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171327_88444 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/measures + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88444. + reviewed_at: '2026-08-12' +- id: usda_171327_88443 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.4 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/measures + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88443. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/onion_yellow.yaml b/culinary/ingredients/onion_yellow.yaml new file mode 100644 index 0000000..55d1cb2 --- /dev/null +++ b/culinary/ingredients/onion_yellow.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: onion_yellow +name: Onions, yellow, raw +status: active +categories: +- unknown +aliases: +- name: fresh yellow onion + kind: common +- name: onion, yellow, fresh + kind: search +nutrition_mapping_ids: +- usda_fdc_onion_yellow_790646 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/orange_extract.yaml b/culinary/ingredients/orange_extract.yaml new file mode 100644 index 0000000..08fe700 --- /dev/null +++ b/culinary/ingredients/orange_extract.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: orange_extract +name: orange extract +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/orange_juice.yaml b/culinary/ingredients/orange_juice.yaml new file mode 100644 index 0000000..f84e68e --- /dev/null +++ b/culinary/ingredients/orange_juice.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: orange_juice +name: Orange juice, no pulp, not fortified, not from concentrate, refrigerated +status: active +categories: +- unknown +aliases: +- name: orange juice + kind: search +nutrition_mapping_ids: +- usda_fdc_orange_juice_2003597 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/orange_juice_concentrate.yaml b/culinary/ingredients/orange_juice_concentrate.yaml new file mode 100644 index 0000000..70743d7 --- /dev/null +++ b/culinary/ingredients/orange_juice_concentrate.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: orange_juice_concentrate +name: Orange juice, frozen concentrate, unsweetened, undiluted +status: active +categories: +- unknown +aliases: +- name: orange juice concentrate + kind: search +nutrition_mapping_ids: +- usda_fdc_orange_juice_concentrate_169923 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169923_85687 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 262.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169923' + url: https://fdc.nal.usda.gov/food-details/169923/measures + title: Orange juice, frozen concentrate, unsweetened, undiluted + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85687. + reviewed_at: '2026-08-12' +- id: usda_169923_85688 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 33.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169923' + url: https://fdc.nal.usda.gov/food-details/169923/measures + title: Orange juice, frozen concentrate, unsweetened, undiluted + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85688. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/orange_zest.yaml b/culinary/ingredients/orange_zest.yaml new file mode 100644 index 0000000..bd28d57 --- /dev/null +++ b/culinary/ingredients/orange_zest.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: orange_zest +name: Orange peel, raw +status: active +categories: +- unknown +aliases: +- name: orange zest + kind: search +nutrition_mapping_ids: +- usda_fdc_orange_zest_169103 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169103_84243 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169103' + url: https://fdc.nal.usda.gov/food-details/169103/measures + title: Orange peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 84243. + reviewed_at: '2026-08-12' +- id: usda_169103_84244 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '169103' + url: https://fdc.nal.usda.gov/food-details/169103/measures + title: Orange peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 84244. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/oregano.yaml b/culinary/ingredients/oregano.yaml new file mode 100644 index 0000000..1aa50ad --- /dev/null +++ b/culinary/ingredients/oregano.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: oregano +name: Spices, oregano, dried +status: active +categories: +- unknown +aliases: +- name: oregano + kind: search +nutrition_mapping_ids: +- usda_fdc_oregano_171328 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171328_88445 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 1.0 + unit_id: gram + state: leaves + source: + source_type: usda_fdc + external_id: '171328' + url: https://fdc.nal.usda.gov/food-details/171328/measures + title: Spices, oregano, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88445. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/oyster_sauce.yaml b/culinary/ingredients/oyster_sauce.yaml new file mode 100644 index 0000000..646901c --- /dev/null +++ b/culinary/ingredients/oyster_sauce.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: oyster_sauce +name: Sauce, oyster, ready-to-serve +status: active +categories: +- sauce +aliases: +- name: oyster sauce + kind: search +nutrition_mapping_ids: +- usda_fdc_oyster_sauce_174529 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174529_94524 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 18.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174529' + url: https://fdc.nal.usda.gov/food-details/174529/measures + title: Sauce, oyster, ready-to-serve + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94524. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/paprika.yaml b/culinary/ingredients/paprika.yaml new file mode 100644 index 0000000..3cea6f0 --- /dev/null +++ b/culinary/ingredients/paprika.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: paprika +name: Spices, paprika +status: active +categories: +- unknown +aliases: +- name: paprika + kind: search +nutrition_mapping_ids: +- usda_fdc_paprika_171329 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171329_88448 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 6.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171329' + url: https://fdc.nal.usda.gov/food-details/171329/measures + title: Spices, paprika + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88448. + reviewed_at: '2026-08-12' +- id: usda_171329_88447 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171329' + url: https://fdc.nal.usda.gov/food-details/171329/measures + title: Spices, paprika + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88447. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/parmesan_cheese.yaml b/culinary/ingredients/parmesan_cheese.yaml new file mode 100644 index 0000000..17c1acf --- /dev/null +++ b/culinary/ingredients/parmesan_cheese.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: parmesan_cheese +name: Cheese, parmesan, grated +status: active +categories: +- dairy +aliases: +- name: canned grated Parmesan + kind: common +- name: Parmesan cheese, dry grated + kind: search +nutrition_mapping_ids: +- usda_fdc_parmesan_cheese_171247 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171247_88261 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 100.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171247' + url: https://fdc.nal.usda.gov/food-details/171247/measures + title: Cheese, parmesan, grated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88261. + reviewed_at: '2026-08-12' +- id: usda_171247_88262 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 5.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171247' + url: https://fdc.nal.usda.gov/food-details/171247/measures + title: Cheese, parmesan, grated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88262. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/parsley.yaml b/culinary/ingredients/parsley.yaml new file mode 100644 index 0000000..870968b --- /dev/null +++ b/culinary/ingredients/parsley.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: parsley +name: Parsley, fresh +status: active +categories: +- herb +aliases: +- name: parsley + kind: search +nutrition_mapping_ids: +- usda_fdc_parsley_170416 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170416_86607 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 60.0 + unit_id: gram + state: chopped + source: + source_type: usda_fdc + external_id: '170416' + url: https://fdc.nal.usda.gov/food-details/170416/measures + title: Parsley, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86607. + reviewed_at: '2026-08-12' +- id: usda_170416_86608 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 3.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170416' + url: https://fdc.nal.usda.gov/food-details/170416/measures + title: Parsley, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86608. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/peanut_butter.yaml b/culinary/ingredients/peanut_butter.yaml new file mode 100644 index 0000000..69d348e --- /dev/null +++ b/culinary/ingredients/peanut_butter.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: peanut_butter +name: Peanut butter, creamy +status: active +categories: +- fat +aliases: +- name: peanut butter + kind: search +nutrition_mapping_ids: +- usda_fdc_peanut_butter_2262072 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/pickle_juice.yaml b/culinary/ingredients/pickle_juice.yaml new file mode 100644 index 0000000..2dbf3bf --- /dev/null +++ b/culinary/ingredients/pickle_juice.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: pickle_juice +name: pickle juice +status: active +categories: +- acid +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/pineapple_crushed_in_juice.yaml b/culinary/ingredients/pineapple_crushed_in_juice.yaml new file mode 100644 index 0000000..f61a1de --- /dev/null +++ b/culinary/ingredients/pineapple_crushed_in_juice.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: pineapple_crushed_in_juice +name: Pineapple, canned, juice pack, solids and liquids +status: active +categories: +- produce +aliases: +- name: pineapple, crushed, in juice + kind: search +nutrition_mapping_ids: +- usda_fdc_pineapple_crushed_in_juice_169126 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_169126_84294 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 249.0 + unit_id: gram + state: crushed, sliced, or chunks + source: + source_type: usda_fdc + external_id: '169126' + url: https://fdc.nal.usda.gov/food-details/169126/measures + title: Pineapple, canned, juice pack, solids and liquids + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 84294. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/pinto_beans_dry_uncooked.yaml b/culinary/ingredients/pinto_beans_dry_uncooked.yaml new file mode 100644 index 0000000..d2b67dd --- /dev/null +++ b/culinary/ingredients/pinto_beans_dry_uncooked.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: pinto_beans_dry_uncooked +name: Beans, Dry, Pinto (0% moisture) +status: active +categories: +- unknown +aliases: +- name: pinto beans, dry, uncooked + kind: search +nutrition_mapping_ids: +- usda_fdc_pinto_beans_dry_uncooked_747445 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/pistachio_nuts.yaml b/culinary/ingredients/pistachio_nuts.yaml new file mode 100644 index 0000000..c7984c9 --- /dev/null +++ b/culinary/ingredients/pistachio_nuts.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: pistachio_nuts +name: Nuts, pistachio nuts, raw +status: active +categories: +- inclusion +aliases: +- name: pistachio nuts + kind: search +nutrition_mapping_ids: +- usda_fdc_pistachio_nuts_2515379 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/potato_russet.yaml b/culinary/ingredients/potato_russet.yaml new file mode 100644 index 0000000..1284b51 --- /dev/null +++ b/culinary/ingredients/potato_russet.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: potato_russet +name: Potatoes, russet, flesh and skin, raw (Includes foods for USDA's Food Distribution + Program) +status: active +categories: +- unknown +aliases: +- name: russet potato + kind: search +nutrition_mapping_ids: +- usda_fdc_potato_russet_170027 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170027_85921 + from: + quantity: 0.5 + unit_id: cup_us + to: + quantity: 75.0 + unit_id: gram + state: diced + source: + source_type: usda_fdc + external_id: '170027' + url: https://fdc.nal.usda.gov/food-details/170027/measures + title: Potatoes, russet, flesh and skin, raw (Includes foods for USDA's Food Distribution + Program) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85921. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/provolone_cheese.yaml b/culinary/ingredients/provolone_cheese.yaml new file mode 100644 index 0000000..b4bd33b --- /dev/null +++ b/culinary/ingredients/provolone_cheese.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: provolone_cheese +name: Cheese, provolone +status: active +categories: +- dairy +aliases: +- name: provolone cheese + kind: search +nutrition_mapping_ids: +- usda_fdc_provolone_cheese_170850 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170850_87396 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 132.0 + unit_id: gram + state: diced + source: + source_type: usda_fdc + external_id: '170850' + url: https://fdc.nal.usda.gov/food-details/170850/measures + title: Cheese, provolone + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87396. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/pumpkin_puree.yaml b/culinary/ingredients/pumpkin_puree.yaml new file mode 100644 index 0000000..f6daee0 --- /dev/null +++ b/culinary/ingredients/pumpkin_puree.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: pumpkin_puree +name: Pumpkin, canned, without salt +status: active +categories: +- other +aliases: +- name: pumpkin puree + kind: search +nutrition_mapping_ids: +- usda_fdc_pumpkin_puree_168450 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168450_83114 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 245.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '168450' + url: https://fdc.nal.usda.gov/food-details/168450/measures + title: Pumpkin, canned, without salt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83114. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/raisins.yaml b/culinary/ingredients/raisins.yaml new file mode 100644 index 0000000..34caab2 --- /dev/null +++ b/culinary/ingredients/raisins.yaml @@ -0,0 +1,13 @@ +schema_version: 2 +id: raisins +name: Raisins, dark, seedless +status: active +categories: +- inclusion +aliases: +- name: raisins + kind: search +nutrition_mapping_ids: +- usda_fdc_raisins_2758980 +allergen_mapping_ids: [] +measure_conversions: [] diff --git a/culinary/ingredients/ranch.yaml b/culinary/ingredients/ranch.yaml new file mode 100644 index 0000000..6d713b5 --- /dev/null +++ b/culinary/ingredients/ranch.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: ranch +name: Salad dressing, ranch dressing, regular +status: active +categories: +- unknown +aliases: +- name: ranch + kind: search +nutrition_mapping_ids: +- usda_fdc_ranch_173592 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_173592_92892 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 15.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173592' + url: https://fdc.nal.usda.gov/food-details/173592/measures + title: Salad dressing, ranch dressing, regular + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92892. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/raspberry.yaml b/culinary/ingredients/raspberry.yaml new file mode 100644 index 0000000..3a4e0e2 --- /dev/null +++ b/culinary/ingredients/raspberry.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: raspberry +name: Raspberries, raw +status: active +categories: +- fruit +aliases: +- name: raspberry + kind: common +- name: raspberries + kind: search +nutrition_mapping_ids: +- usda_fdc_raspberry_2346410 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/raw_broccoli.yaml b/culinary/ingredients/raw_broccoli.yaml new file mode 100644 index 0000000..606719d --- /dev/null +++ b/culinary/ingredients/raw_broccoli.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: raw_broccoli +name: Broccoli, raw +status: active +categories: +- unknown +aliases: +- name: raw broccoli + kind: search +nutrition_mapping_ids: +- usda_fdc_raw_broccoli_747447 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/red_curry_paste.yaml b/culinary/ingredients/red_curry_paste.yaml new file mode 100644 index 0000000..eee14cc --- /dev/null +++ b/culinary/ingredients/red_curry_paste.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: red_curry_paste +name: Thai Kitchen red curry paste +status: active +categories: +- condiment +- curry_paste +aliases: +- name: Thai Kitchen gluten-free red curry paste + kind: trade +- name: red curry paste + kind: common +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/rice.yaml b/culinary/ingredients/rice.yaml new file mode 100644 index 0000000..1396999 --- /dev/null +++ b/culinary/ingredients/rice.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: rice +name: Rice, white, long grain, unenriched, raw +status: active +categories: +- unknown +aliases: +- name: uncooked long-grain white rice + kind: common +- name: white long-grain rice, dry + kind: search +nutrition_mapping_ids: +- usda_fdc_rice_2512381 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/rice_chex.yaml b/culinary/ingredients/rice_chex.yaml new file mode 100644 index 0000000..b2b7fff --- /dev/null +++ b/culinary/ingredients/rice_chex.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: rice_chex +name: RICE SQUARES TOASTED CEREAL, RICE SQUARES +status: active +categories: +- unknown +aliases: +- name: generic Rice Chex-style cereal + kind: search +- name: crisp rice square cereal, generic + kind: search +nutrition_mapping_ids: +- usda_fdc_rice_chex_2311632 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/rice_cooked.yaml b/culinary/ingredients/rice_cooked.yaml new file mode 100644 index 0000000..dcf8572 --- /dev/null +++ b/culinary/ingredients/rice_cooked.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: "rice_cooked" +name: "Rice, white, long-grain, regular, enriched, cooked" +status: "active" +categories: + - "unknown" +aliases: + - name: "rice, cooked" + kind: "search" +nutrition_mapping_ids: + - "usda_fdc_rice_cooked_168878" +allergen_mapping_ids: [] +measure_conversions: + - id: "usda_168878_83928" + from: + quantity: 1 + unit_id: "cup_us" + to: + quantity: 158 + unit_id: "gram" + source: + source_type: "usda_fdc" + external_id: "168878" + url: "https://fdc.nal.usda.gov/food-details/168878/measures" + title: "Rice, white, long-grain, regular, enriched, cooked" + publisher: "USDA Agricultural Research Service" + retrieved_at: "2026-08-12" + reviewed: true + reviewed_at: "2026-08-12" + notes: "FoodData Central portion ID 83928." diff --git a/culinary/ingredients/salt.yaml b/culinary/ingredients/salt.yaml new file mode 100644 index 0000000..7a90607 --- /dev/null +++ b/culinary/ingredients/salt.yaml @@ -0,0 +1,66 @@ +schema_version: 2 +id: salt +name: Salt, table +status: active +categories: +- salt +aliases: +- name: salt + kind: search +- name: kosher salt + kind: search +nutrition_mapping_ids: +- usda_fdc_salt_173468 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_173468_92596 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 292.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173468' + url: https://fdc.nal.usda.gov/food-details/173468/measures + title: Salt, table + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92596. + reviewed_at: '2026-08-12' +- id: usda_173468_92594 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 6.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173468' + url: https://fdc.nal.usda.gov/food-details/173468/measures + title: Salt, table + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92594. + reviewed_at: '2026-08-12' +- id: usda_173468_92595 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 18.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173468' + url: https://fdc.nal.usda.gov/food-details/173468/measures + title: Salt, table + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92595. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/sambal_oelek.yaml b/culinary/ingredients/sambal_oelek.yaml new file mode 100644 index 0000000..3b90f3c --- /dev/null +++ b/culinary/ingredients/sambal_oelek.yaml @@ -0,0 +1,11 @@ +schema_version: 2 +id: sambal_oelek +name: Huy Fong Foods sambal oelek +status: active +categories: +- unknown +aliases: +- name: Huy Fong sambal oelek + kind: trade +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/semisweet_chocolate.yaml b/culinary/ingredients/semisweet_chocolate.yaml new file mode 100644 index 0000000..b103f69 --- /dev/null +++ b/culinary/ingredients/semisweet_chocolate.yaml @@ -0,0 +1,39 @@ +schema_version: 2 +id: semisweet_chocolate +name: Candies, semisweet chocolate +status: active +categories: +- unknown +aliases: +- name: semisweet chocolate + kind: search +- name: bittersweet chocolate + kind: search +- name: semisweet chocolate chips + kind: search +- name: chopped semisweet chocolate chunks + kind: search +- name: chocolate chunks, semisweet, chopped + kind: search +nutrition_mapping_ids: +- usda_fdc_semisweet_chocolate_167976 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_167976_82317 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 173.0 + unit_id: gram + state: mini chips + source: + source_type: usda_fdc + external_id: '167976' + url: https://fdc.nal.usda.gov/food-details/167976/measures + title: Candies, semisweet chocolate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 82317. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/sesame_oil.yaml b/culinary/ingredients/sesame_oil.yaml new file mode 100644 index 0000000..236f6f0 --- /dev/null +++ b/culinary/ingredients/sesame_oil.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: sesame_oil +name: Oil, sesame, salad or cooking +status: active +categories: +- fat +aliases: +- name: sesame oil + kind: search +nutrition_mapping_ids: +- usda_fdc_sesame_oil_171016 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171016_87777 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 13.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171016' + url: https://fdc.nal.usda.gov/food-details/171016/measures + title: Oil, sesame, salad or cooking + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87777. + reviewed_at: '2026-08-12' +- id: usda_171016_87779 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171016' + url: https://fdc.nal.usda.gov/food-details/171016/measures + title: Oil, sesame, salad or cooking + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87779. + reviewed_at: '2026-08-12' +- id: usda_171016_87778 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 218.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171016' + url: https://fdc.nal.usda.gov/food-details/171016/measures + title: Oil, sesame, salad or cooking + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87778. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/shaoxing_wine.yaml b/culinary/ingredients/shaoxing_wine.yaml new file mode 100644 index 0000000..1c559e3 --- /dev/null +++ b/culinary/ingredients/shaoxing_wine.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: shaoxing_wine +name: SHAOHSING RICE COOKING WINE +status: active +categories: +- alcohol +aliases: +- name: shaoxing wine + kind: search +nutrition_mapping_ids: +- usda_fdc_shaoxing_wine_2440010 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/sharp_cheddar_cheese.yaml b/culinary/ingredients/sharp_cheddar_cheese.yaml new file mode 100644 index 0000000..e58aa3d --- /dev/null +++ b/culinary/ingredients/sharp_cheddar_cheese.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: sharp_cheddar_cheese +name: Cheese, cheddar, sharp, sliced +status: active +categories: +- unknown +aliases: +- name: sharp cheddar cheese + kind: search +nutrition_mapping_ids: +- usda_fdc_sharp_cheddar_cheese_170899 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/shortening.yaml b/culinary/ingredients/shortening.yaml new file mode 100644 index 0000000..9efa2de --- /dev/null +++ b/culinary/ingredients/shortening.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: shortening +name: Shortening, vegetable, household, composite +status: active +categories: +- fat +aliases: +- name: shortening + kind: search +nutrition_mapping_ids: +- usda_fdc_shortening_173584 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_173584_92880 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 12.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173584' + url: https://fdc.nal.usda.gov/food-details/173584/measures + title: Shortening, vegetable, household, composite + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92880. + reviewed_at: '2026-08-12' +- id: usda_173584_92881 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 205.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173584' + url: https://fdc.nal.usda.gov/food-details/173584/measures + title: Shortening, vegetable, household, composite + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92881. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/sodium_citrate.yaml b/culinary/ingredients/sodium_citrate.yaml new file mode 100644 index 0000000..0334260 --- /dev/null +++ b/culinary/ingredients/sodium_citrate.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: sodium_citrate +name: sodium citrate +status: active +categories: +- unknown +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/sour_cream.yaml b/culinary/ingredients/sour_cream.yaml new file mode 100644 index 0000000..8a0e325 --- /dev/null +++ b/culinary/ingredients/sour_cream.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: sour_cream +name: Cream, sour, cultured +status: active +categories: +- liquid +aliases: +- name: sour cream + kind: search +nutrition_mapping_ids: +- usda_fdc_sour_cream_171257 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171257_88296 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 12.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171257' + url: https://fdc.nal.usda.gov/food-details/171257/measures + title: Cream, sour, cultured + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88296. + reviewed_at: '2026-08-12' +- id: usda_171257_88297 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 230.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171257' + url: https://fdc.nal.usda.gov/food-details/171257/measures + title: Cream, sour, cultured + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88297. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/soy_sauce_dark.yaml b/culinary/ingredients/soy_sauce_dark.yaml new file mode 100644 index 0000000..e9a1e2b --- /dev/null +++ b/culinary/ingredients/soy_sauce_dark.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: soy_sauce_dark +name: Lee Kum Kee Premium Dark Soy Sauce +status: active +categories: +- sauce +aliases: +- name: Lee Kum Kee dark soy sauce + kind: trade +- name: dark soy sauce + kind: common +nutrition_mapping_ids: +- supplier_label_lee_kum_kee_premium_dark_soy_sauce_078895126389 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/soy_sauce_light.yaml b/culinary/ingredients/soy_sauce_light.yaml new file mode 100644 index 0000000..e291ff2 --- /dev/null +++ b/culinary/ingredients/soy_sauce_light.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: soy_sauce_light +name: Soy sauce made from soy and wheat (shoyu) +status: active +categories: +- sauce +aliases: +- name: soy sauce, light + kind: search +nutrition_mapping_ids: +- usda_fdc_soy_sauce_light_174277 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174277_94068 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 16.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174277' + url: https://fdc.nal.usda.gov/food-details/174277/measures + title: Soy sauce made from soy and wheat (shoyu) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94068. + reviewed_at: '2026-08-12' +- id: usda_174277_94069 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 5.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174277' + url: https://fdc.nal.usda.gov/food-details/174277/measures + title: Soy sauce made from soy and wheat (shoyu) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94069. + reviewed_at: '2026-08-12' +- id: usda_174277_94070 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 255.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174277' + url: https://fdc.nal.usda.gov/food-details/174277/measures + title: Soy sauce made from soy and wheat (shoyu) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94070. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/soy_sauce_light_low_sodium.yaml b/culinary/ingredients/soy_sauce_light_low_sodium.yaml new file mode 100644 index 0000000..750d315 --- /dev/null +++ b/culinary/ingredients/soy_sauce_light_low_sodium.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: soy_sauce_light_low_sodium +name: Soy sauce made from soy and wheat (shoyu), low sodium +status: active +categories: +- sauce +aliases: +- name: soy sauce, light, low sodium + kind: search +nutrition_mapping_ids: +- usda_fdc_soy_sauce_light_low_sodium_172473 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172473_90678 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172473' + url: https://fdc.nal.usda.gov/food-details/172473/measures + title: Soy sauce made from soy and wheat (shoyu), low sodium + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90678. + reviewed_at: '2026-08-12' +- id: usda_172473_90677 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 14.2 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172473' + url: https://fdc.nal.usda.gov/food-details/172473/measures + title: Soy sauce made from soy and wheat (shoyu), low sodium + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90677. + reviewed_at: '2026-08-12' +- id: usda_172473_90679 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 255.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172473' + url: https://fdc.nal.usda.gov/food-details/172473/measures + title: Soy sauce made from soy and wheat (shoyu), low sodium + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90679. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/soybean_oil.yaml b/culinary/ingredients/soybean_oil.yaml new file mode 100644 index 0000000..e26d2e6 --- /dev/null +++ b/culinary/ingredients/soybean_oil.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: soybean_oil +name: Oil, soybean +status: active +categories: +- fat +aliases: +- name: soybean oil + kind: search +nutrition_mapping_ids: +- usda_fdc_soybean_oil_748366 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_748366_192348 + from: + quantity: 100.0 + unit_id: milliliter + to: + quantity: 91.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '748366' + url: https://fdc.nal.usda.gov/food-details/748366/measures + title: Oil, soybean + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 192348. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/spice_blend.yaml b/culinary/ingredients/spice_blend.yaml new file mode 100644 index 0000000..5fc6fbe --- /dev/null +++ b/culinary/ingredients/spice_blend.yaml @@ -0,0 +1,9 @@ +schema_version: 2 +id: spice_blend +name: spice blend +status: active +categories: +- spice +aliases: [] +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/sriracha.yaml b/culinary/ingredients/sriracha.yaml new file mode 100644 index 0000000..51f2ca6 --- /dev/null +++ b/culinary/ingredients/sriracha.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: sriracha +name: Sauce, hot chile, sriracha +status: active +categories: +- unknown +aliases: +- name: sriracha + kind: search +nutrition_mapping_ids: +- usda_fdc_sriracha_171186 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171186_88133 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 6.5 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171186' + url: https://fdc.nal.usda.gov/food-details/171186/measures + title: Sauce, hot chile, sriracha + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 88133. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/sugar.yaml b/culinary/ingredients/sugar.yaml new file mode 100644 index 0000000..947fd51 --- /dev/null +++ b/culinary/ingredients/sugar.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: sugar +name: Sugars, granulated +status: active +categories: +- sweetener +aliases: +- name: sugar + kind: search +nutrition_mapping_ids: +- usda_fdc_sugar_746784 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_746784_187533 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '746784' + url: https://fdc.nal.usda.gov/food-details/746784/measures + title: Sugars, granulated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 187533. + reviewed_at: '2026-08-12' +- id: usda_746784_187534 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 188.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '746784' + url: https://fdc.nal.usda.gov/food-details/746784/measures + title: Sugars, granulated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 187534. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/sweet_potato_cooked.yaml b/culinary/ingredients/sweet_potato_cooked.yaml new file mode 100644 index 0000000..6ded093 --- /dev/null +++ b/culinary/ingredients/sweet_potato_cooked.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: sweet_potato_cooked +name: Sweet potato, cooked, boiled, without skin +status: active +categories: +- produce +aliases: +- name: sweet potato, cooked + kind: search +nutrition_mapping_ids: +- usda_fdc_sweet_potato_cooked_168484 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_168484_83172 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 328.0 + unit_id: gram + state: mashed + source: + source_type: usda_fdc + external_id: '168484' + url: https://fdc.nal.usda.gov/food-details/168484/measures + title: Sweet potato, cooked, boiled, without skin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 83172. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/tahini.yaml b/culinary/ingredients/tahini.yaml new file mode 100644 index 0000000..028de9d --- /dev/null +++ b/culinary/ingredients/tahini.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: tahini +name: Seeds, sesame butter, tahini, from roasted and toasted kernels (most common + type) +status: active +categories: +- seed_paste +aliases: +- name: tahini + kind: search +nutrition_mapping_ids: +- usda_fdc_tahini_170189 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170189_86209 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 15.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170189' + url: https://fdc.nal.usda.gov/food-details/170189/measures + title: Seeds, sesame butter, tahini, from roasted and toasted kernels (most common + type) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 86209. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/tapioca_starch.yaml b/culinary/ingredients/tapioca_starch.yaml new file mode 100644 index 0000000..b71da07 --- /dev/null +++ b/culinary/ingredients/tapioca_starch.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: tapioca_starch +name: TAPIOCA STARCH +status: active +categories: +- starch +aliases: [] +nutrition_mapping_ids: +- usda_fdc_tapioca_starch_2033785 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/tomato_bouillon.yaml b/culinary/ingredients/tomato_bouillon.yaml new file mode 100644 index 0000000..d3dc6f5 --- /dev/null +++ b/culinary/ingredients/tomato_bouillon.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: tomato_bouillon +name: TOMATO BOUILLON WITH CHICKEN FLAVOR, TOMATO WITH CHICKEN +status: active +categories: +- seasoning +aliases: +- name: Knorr Caldo de Tomate + kind: trade +- name: Knorr tomato bouillon with chicken flavor + kind: search +nutrition_mapping_ids: +- usda_fdc_tomato_bouillon_2029306 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/tomato_crushed_in_juice.yaml b/culinary/ingredients/tomato_crushed_in_juice.yaml new file mode 100644 index 0000000..a88a19e --- /dev/null +++ b/culinary/ingredients/tomato_crushed_in_juice.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: tomato_crushed_in_juice +name: Tomatoes, red, ripe, canned, packed in tomato juice +status: active +categories: +- produce +aliases: +- name: tomato, crushed, in juice + kind: search +nutrition_mapping_ids: +- usda_fdc_tomato_crushed_in_juice_170051 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170051_85963 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 240.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170051' + url: https://fdc.nal.usda.gov/food-details/170051/measures + title: Tomatoes, red, ripe, canned, packed in tomato juice + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85963. + reviewed_at: '2026-08-12' +- id: usda_170051_85964 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 15.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '170051' + url: https://fdc.nal.usda.gov/food-details/170051/measures + title: Tomatoes, red, ripe, canned, packed in tomato juice + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 85964. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/tomato_paste.yaml b/culinary/ingredients/tomato_paste.yaml new file mode 100644 index 0000000..fee03a4 --- /dev/null +++ b/culinary/ingredients/tomato_paste.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: tomato_paste +name: Tomato, paste, canned, without salt added +status: active +categories: +- produce +aliases: +- name: tomato paste + kind: search +nutrition_mapping_ids: +- usda_fdc_tomato_paste_2685580 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/tomato_puree.yaml b/culinary/ingredients/tomato_puree.yaml new file mode 100644 index 0000000..206ee0c --- /dev/null +++ b/culinary/ingredients/tomato_puree.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: tomato_puree +name: Tomato, puree, canned +status: active +categories: +- unknown +aliases: +- name: tomato puree + kind: search +nutrition_mapping_ids: +- usda_fdc_tomato_puree_2685582 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/vanilla_extract.yaml b/culinary/ingredients/vanilla_extract.yaml new file mode 100644 index 0000000..e9fc07d --- /dev/null +++ b/culinary/ingredients/vanilla_extract.yaml @@ -0,0 +1,62 @@ +schema_version: 2 +id: vanilla_extract +name: Vanilla extract +status: active +categories: +- flavoring +aliases: [] +nutrition_mapping_ids: +- usda_fdc_vanilla_extract_173471 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_173471_92603 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 4.2 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173471' + url: https://fdc.nal.usda.gov/food-details/173471/measures + title: Vanilla extract + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92603. + reviewed_at: '2026-08-12' +- id: usda_173471_92605 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 208.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173471' + url: https://fdc.nal.usda.gov/food-details/173471/measures + title: Vanilla extract + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92605. + reviewed_at: '2026-08-12' +- id: usda_173471_92604 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 13.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173471' + url: https://fdc.nal.usda.gov/food-details/173471/measures + title: Vanilla extract + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92604. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/vegetables_mixed.yaml b/culinary/ingredients/vegetables_mixed.yaml new file mode 100644 index 0000000..cb24aae --- /dev/null +++ b/culinary/ingredients/vegetables_mixed.yaml @@ -0,0 +1,11 @@ +schema_version: 2 +id: vegetables_mixed +name: Frozen stir-fry vegetable blend +status: active +categories: +- vegetable +aliases: +- name: mixed vegetables + kind: search +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/ingredients/vinegar_5.yaml b/culinary/ingredients/vinegar_5.yaml new file mode 100644 index 0000000..1bb0f78 --- /dev/null +++ b/culinary/ingredients/vinegar_5.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: vinegar_5 +name: Vinegar, distilled +status: active +categories: +- other +aliases: +- name: vinegar 5% + kind: search +nutrition_mapping_ids: +- usda_fdc_vinegar_5_172237 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172237_90136 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 14.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172237' + url: https://fdc.nal.usda.gov/food-details/172237/measures + title: Vinegar, distilled + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90136. + reviewed_at: '2026-08-12' +- id: usda_172237_90138 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 5.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172237' + url: https://fdc.nal.usda.gov/food-details/172237/measures + title: Vinegar, distilled + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90138. + reviewed_at: '2026-08-12' +- id: usda_172237_90137 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 238.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172237' + url: https://fdc.nal.usda.gov/food-details/172237/measures + title: Vinegar, distilled + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90137. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/vinegar_apple_cider.yaml b/culinary/ingredients/vinegar_apple_cider.yaml new file mode 100644 index 0000000..0ea512c --- /dev/null +++ b/culinary/ingredients/vinegar_apple_cider.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: vinegar_apple_cider +name: Vinegar, cider +status: active +categories: +- unknown +aliases: +- name: apple cider vinegar + kind: search +nutrition_mapping_ids: +- usda_fdc_vinegar_apple_cider_173469 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_173469_92600 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 5.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173469' + url: https://fdc.nal.usda.gov/food-details/173469/measures + title: Vinegar, cider + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92600. + reviewed_at: '2026-08-12' +- id: usda_173469_92598 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 14.9 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173469' + url: https://fdc.nal.usda.gov/food-details/173469/measures + title: Vinegar, cider + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92598. + reviewed_at: '2026-08-12' +- id: usda_173469_92599 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 239.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '173469' + url: https://fdc.nal.usda.gov/food-details/173469/measures + title: Vinegar, cider + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 92599. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/vinegar_balsamic.yaml b/culinary/ingredients/vinegar_balsamic.yaml new file mode 100644 index 0000000..3f4f9dd --- /dev/null +++ b/culinary/ingredients/vinegar_balsamic.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: vinegar_balsamic +name: Vinegar, balsamic +status: active +categories: +- unknown +aliases: +- name: balsamic vinegar + kind: search +nutrition_mapping_ids: +- usda_fdc_vinegar_balsamic_172241 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_172241_90145 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 16.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172241' + url: https://fdc.nal.usda.gov/food-details/172241/measures + title: Vinegar, balsamic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90145. + reviewed_at: '2026-08-12' +- id: usda_172241_90147 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 5.3 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172241' + url: https://fdc.nal.usda.gov/food-details/172241/measures + title: Vinegar, balsamic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90147. + reviewed_at: '2026-08-12' +- id: usda_172241_90146 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 255.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '172241' + url: https://fdc.nal.usda.gov/food-details/172241/measures + title: Vinegar, balsamic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 90146. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/vinegar_rice.yaml b/culinary/ingredients/vinegar_rice.yaml new file mode 100644 index 0000000..e63ca8b --- /dev/null +++ b/culinary/ingredients/vinegar_rice.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: vinegar_rice +name: MARUKAN, GENUINE BREWED RICE VINEGAR +status: active +categories: +- acid +aliases: +- name: unseasoned rice vinegar + kind: common +- name: rice vinegar, unseasoned + kind: search +nutrition_mapping_ids: +- usda_fdc_vinegar_rice_2085000 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/vodka.yaml b/culinary/ingredients/vodka.yaml new file mode 100644 index 0000000..7dab327 --- /dev/null +++ b/culinary/ingredients/vodka.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: vodka +name: Alcoholic beverage, distilled, vodka, 80 proof +status: active +categories: +- alcohol +aliases: +- name: vodka + kind: search +nutrition_mapping_ids: +- usda_fdc_vodka_174818 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174818_94950 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 27.8 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174818' + url: https://fdc.nal.usda.gov/food-details/174818/measures + title: Alcoholic beverage, distilled, vodka, 80 proof + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 94950. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/walnut.yaml b/culinary/ingredients/walnut.yaml new file mode 100644 index 0000000..dffc0a9 --- /dev/null +++ b/culinary/ingredients/walnut.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: walnut +name: Nuts, walnuts, English, halves, raw +status: active +categories: +- inclusion +aliases: +- name: walnut + kind: search +nutrition_mapping_ids: +- usda_fdc_walnut_2346394 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/water.yaml b/culinary/ingredients/water.yaml new file mode 100644 index 0000000..d83eab8 --- /dev/null +++ b/culinary/ingredients/water.yaml @@ -0,0 +1,25 @@ +schema_version: 2 +id: water +name: water +status: active +categories: +- liquid +aliases: [] +density_measurements: +- id: water_room_temperature + mass: + quantity: 100 + unit_id: gram + volume: + quantity: 100 + unit_id: milliliter + temperature_c: 20 + state: liquid, room temperature; culinary approximation + source: + source_type: manual + title: Culinary 1 g/mL approximation + reviewed: true + notes: Rounded working conversion; not intended as a laboratory density measurement. +nutrition_mapping_ids: [] +allergen_mapping_ids: [] +measure_conversions: [] diff --git a/culinary/ingredients/water_ice.yaml b/culinary/ingredients/water_ice.yaml new file mode 100644 index 0000000..67695f7 --- /dev/null +++ b/culinary/ingredients/water_ice.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: water_ice +name: Water, bottled, generic +status: active +categories: +- unknown +aliases: +- name: water ice + kind: search +nutrition_mapping_ids: +- usda_fdc_water_ice_174158 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_174158_93846 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 237.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174158' + url: https://fdc.nal.usda.gov/food-details/174158/measures + title: Water, bottled, generic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 93846. + reviewed_at: '2026-08-12' +- id: usda_174158_93845 + from: + quantity: 1.0 + unit_id: fluid_ounce_us + to: + quantity: 29.6 + unit_id: gram + source: + source_type: usda_fdc + external_id: '174158' + url: https://fdc.nal.usda.gov/food-details/174158/measures + title: Water, bottled, generic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 93845. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/wheat_gluten_70_80.yaml b/culinary/ingredients/wheat_gluten_70_80.yaml new file mode 100644 index 0000000..d666991 --- /dev/null +++ b/culinary/ingredients/wheat_gluten_70_80.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: wheat_gluten_70_80 +name: Vital wheat gluten +status: active +categories: +- other +aliases: +- name: wheat gluten 70-80% + kind: search +nutrition_mapping_ids: +- usda_fdc_wheat_gluten_70_80_168147 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/white_chocolate.yaml b/culinary/ingredients/white_chocolate.yaml new file mode 100644 index 0000000..b5fd16e --- /dev/null +++ b/culinary/ingredients/white_chocolate.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: white_chocolate +name: Candies, white chocolate +status: active +categories: +- inclusion +aliases: +- name: white chocolate + kind: search +nutrition_mapping_ids: +- usda_fdc_white_chocolate_167571 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_167571_81661 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 14.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '167571' + url: https://fdc.nal.usda.gov/food-details/167571/measures + title: Candies, white chocolate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81661. + reviewed_at: '2026-08-12' +- id: usda_167571_81662 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 170.0 + unit_id: gram + state: chips + source: + source_type: usda_fdc + external_id: '167571' + url: https://fdc.nal.usda.gov/food-details/167571/measures + title: Candies, white chocolate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 81662. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/white_pepper.yaml b/culinary/ingredients/white_pepper.yaml new file mode 100644 index 0000000..64cdc54 --- /dev/null +++ b/culinary/ingredients/white_pepper.yaml @@ -0,0 +1,49 @@ +schema_version: 2 +id: white_pepper +name: Spices, pepper, white +status: active +categories: +- spice +aliases: +- name: white pepper + kind: search +nutrition_mapping_ids: +- usda_fdc_white_pepper_170933 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_170933_87567 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 7.1 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170933' + url: https://fdc.nal.usda.gov/food-details/170933/measures + title: Spices, pepper, white + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87567. + reviewed_at: '2026-08-12' +- id: usda_170933_87566 + from: + quantity: 1.0 + unit_id: teaspoon_us + to: + quantity: 2.4 + unit_id: gram + state: ground + source: + source_type: usda_fdc + external_id: '170933' + url: https://fdc.nal.usda.gov/food-details/170933/measures + title: Spices, pepper, white + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 87566. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/worschestershire_sauce.yaml b/culinary/ingredients/worschestershire_sauce.yaml new file mode 100644 index 0000000..9e4d383 --- /dev/null +++ b/culinary/ingredients/worschestershire_sauce.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: worschestershire_sauce +name: Sauce, worcestershire +status: active +categories: +- unknown +aliases: +- name: worschestershire sauce + kind: search +nutrition_mapping_ids: +- usda_fdc_worschestershire_sauce_171610 +allergen_mapping_ids: [] +measure_conversions: +- id: usda_171610_89071 + from: + quantity: 1.0 + unit_id: cup_us + to: + quantity: 275.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171610' + url: https://fdc.nal.usda.gov/food-details/171610/measures + title: Sauce, worcestershire + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 89071. + reviewed_at: '2026-08-12' +- id: usda_171610_89070 + from: + quantity: 1.0 + unit_id: tablespoon_us + to: + quantity: 17.0 + unit_id: gram + source: + source_type: usda_fdc + external_id: '171610' + url: https://fdc.nal.usda.gov/food-details/171610/measures + title: Sauce, worcestershire + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + notes: FoodData Central portion ID 89070. + reviewed_at: '2026-08-12' diff --git a/culinary/ingredients/xanthan_gum.yaml b/culinary/ingredients/xanthan_gum.yaml new file mode 100644 index 0000000..bd028fd --- /dev/null +++ b/culinary/ingredients/xanthan_gum.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: xanthan_gum +name: XANTHAN GUM +status: active +categories: +- stabilizer +aliases: [] +nutrition_mapping_ids: +- usda_fdc_xanthan_gum_1991838 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/yogurt.yaml b/culinary/ingredients/yogurt.yaml new file mode 100644 index 0000000..fd60ddd --- /dev/null +++ b/culinary/ingredients/yogurt.yaml @@ -0,0 +1,14 @@ +schema_version: 2 +id: yogurt +name: Yogurt, plain, whole milk +status: active +categories: +- unknown +aliases: +- name: plain whole-milk yogurt + kind: common +- name: yogurt, plain whole-milk + kind: search +nutrition_mapping_ids: +- usda_fdc_yogurt_2259793 +allergen_mapping_ids: [] diff --git a/culinary/ingredients/zaatar.yaml b/culinary/ingredients/zaatar.yaml new file mode 100644 index 0000000..b139200 --- /dev/null +++ b/culinary/ingredients/zaatar.yaml @@ -0,0 +1,12 @@ +schema_version: 2 +id: zaatar +name: LEBANON ZAATAR THYME SEASONING +status: active +categories: +- spice +aliases: +- name: za'atar seasoning blend, generic + kind: search +nutrition_mapping_ids: +- usda_fdc_zaatar_2072928 +allergen_mapping_ids: [] diff --git a/culinary/prep_actions/chop.yaml b/culinary/prep_actions/chop.yaml new file mode 100644 index 0000000..e623d98 --- /dev/null +++ b/culinary/prep_actions/chop.yaml @@ -0,0 +1,6 @@ +schema_version: 2 +id: chop +name: chop +action_type: cut +default_yield_factor: 1 +notes: Chop before the ingredient enters the recipe. diff --git a/culinary/prep_actions/crush.yaml b/culinary/prep_actions/crush.yaml new file mode 100644 index 0000000..e21ef68 --- /dev/null +++ b/culinary/prep_actions/crush.yaml @@ -0,0 +1,6 @@ +schema_version: 2 +id: crush +name: crush +action_type: cut +default_yield_factor: 1 +notes: Crush into smaller pieces before the ingredient enters the recipe. diff --git a/culinary/prep_actions/drain.yaml b/culinary/prep_actions/drain.yaml new file mode 100644 index 0000000..e9bc25e --- /dev/null +++ b/culinary/prep_actions/drain.yaml @@ -0,0 +1,5 @@ +schema_version: 2 +id: drain +name: drain +action_type: drain +notes: Remove packing or cooking liquid before weighing usable material. diff --git a/culinary/prep_actions/grate.yaml b/culinary/prep_actions/grate.yaml new file mode 100644 index 0000000..13533d1 --- /dev/null +++ b/culinary/prep_actions/grate.yaml @@ -0,0 +1,6 @@ +schema_version: 2 +id: grate +name: grate +action_type: cut +default_yield_factor: 1 +notes: Grate before the ingredient enters the recipe. diff --git a/culinary/prep_actions/mince.yaml b/culinary/prep_actions/mince.yaml new file mode 100644 index 0000000..2fe0947 --- /dev/null +++ b/culinary/prep_actions/mince.yaml @@ -0,0 +1,6 @@ +schema_version: 2 +id: mince +name: mince +action_type: cut +default_yield_factor: 1 +notes: Cut into very small pieces before the ingredient enters the recipe. diff --git a/culinary/prep_actions/peel.yaml b/culinary/prep_actions/peel.yaml new file mode 100644 index 0000000..1b0adc0 --- /dev/null +++ b/culinary/prep_actions/peel.yaml @@ -0,0 +1,5 @@ +schema_version: 2 +id: peel +name: peel +action_type: peel +notes: Remove peel or skin before the ingredient enters the recipe. diff --git a/culinary/prep_actions/trim.yaml b/culinary/prep_actions/trim.yaml new file mode 100644 index 0000000..29c898c --- /dev/null +++ b/culinary/prep_actions/trim.yaml @@ -0,0 +1,5 @@ +schema_version: 2 +id: trim +name: trim +action_type: trim +notes: Remove unusable exterior, connective tissue, or other specified trim. diff --git a/culinary/purchase_items/sams_club_0980250647.yaml b/culinary/purchase_items/sams_club_0980250647.yaml new file mode 100644 index 0000000..89fd324 --- /dev/null +++ b/culinary/purchase_items/sams_club_0980250647.yaml @@ -0,0 +1,20 @@ +schema_version: 2 +id: sams_club_0980250647 +ingredient_id: sugar +name: 10 LB SUGAR +supplier_id: sams_club +supplier_sku: 0980250647 +status: active +package: + quantity: 10.0 + unit_id: pound +prices: +- amount: 6.58 + currency: USD + effective_at: '2026-07-10' + source: + source_type: supplier + title: Sam's Club receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10295081.yaml b/culinary/purchase_items/walmart_10295081.yaml new file mode 100644 index 0000000..1263fb3 --- /dev/null +++ b/culinary/purchase_items/walmart_10295081.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10295081 +ingredient_id: tomato_paste +name: "Hunt\u2019s Tomato Paste, Perfect for Chili & Soups, 12 oz. Can" +supplier_id: walmart +supplier_sku: '10295081' +status: active +package: + quantity: 12.0 + unit_id: ounce_mass +prices: +- amount: 1.72 + currency: USD + effective_at: '2026-07-29' + source: + source_type: supplier + url: https://www.walmart.com/orders/29788178867501257987?storePurchase=true&source=sco&comm-msg-id=072f19de-49e0-3870-9016-3b9bbfb104a3&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10295176.yaml b/culinary/purchase_items/walmart_10295176.yaml new file mode 100644 index 0000000..20605aa --- /dev/null +++ b/culinary/purchase_items/walmart_10295176.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10295176 +ingredient_id: tomato_paste +name: Contadina Canned Tomatoes Canned Tomato Paste, 12 oz Can +supplier_id: walmart +supplier_sku: '10295176' +status: active +package: + quantity: 12.0 + unit_id: ounce_mass +prices: +- amount: 1.93 + currency: USD + effective_at: '2026-07-29' + source: + source_type: supplier + url: https://www.walmart.com/orders/29788178867501257987?storePurchase=true&source=sco&comm-msg-id=072f19de-49e0-3870-9016-3b9bbfb104a3&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315012.yaml b/culinary/purchase_items/walmart_10315012.yaml new file mode 100644 index 0000000..4ffa7ea --- /dev/null +++ b/culinary/purchase_items/walmart_10315012.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10315012 +ingredient_id: brown_sugar +name: Great Value Light Brown Sugar, 32 oz +supplier_id: walmart +supplier_sku: '10315012' +status: active +package: + quantity: 32.0 + unit_id: ounce_mass +prices: +- amount: 1.98 + currency: USD + effective_at: '2026-05-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/97531739020476935200?storePurchase=true&source=sco&comm-msg-id=1e47ee69-4b4f-357d-87c2-f9e9fa4c4efa&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315054.yaml b/culinary/purchase_items/walmart_10315054.yaml new file mode 100644 index 0000000..d580ca2 --- /dev/null +++ b/culinary/purchase_items/walmart_10315054.yaml @@ -0,0 +1,53 @@ +schema_version: 2 +id: walmart_10315054 +ingredient_id: butter +name: Great Value Sweet Cream Unsalted Butter, 16 oz, 4 Sticks +supplier_id: walmart +supplier_sku: '10315054' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 3.67 + currency: USD + effective_at: '2025-11-25' + source: + source_type: supplier + url: https://www.walmart.com/orders/09296263468708521757?storePurchase=true&source=sco&comm-msg-id=094ad539-7853-31e6-ae9c-d880f6b19770&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 3.44 + currency: USD + effective_at: '2026-03-17' + source: + source_type: supplier + url: https://www.walmart.com/orders/45212490664656751676?storePurchase=true&source=sco&comm-msg-id=80472a52-a1ec-31be-afb2-d769681e3fd7&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 3.06 + currency: USD + effective_at: '2026-04-02' + source: + source_type: supplier + url: https://www.walmart.com/orders/32212589644659780686?storePurchase=true&source=sco&comm-msg-id=bdd4f76a-52e7-39ff-864c-e9dbcb66dbac&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 3.06 + currency: USD + effective_at: '2026-06-29' + source: + source_type: supplier + url: https://www.walmart.com/orders/59188434776500223977?storePurchase=true&source=sco&comm-msg-id=1f48343d-ae31-3bad-9da4-eb56c957ab2e&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 3.06 + currency: USD + effective_at: '2026-08-08' + source: + source_type: supplier + url: https://www.walmart.com/orders/23769992985344078333?storePurchase=true&source=sco&comm-msg-id=c4d34476-32e4-3e79-ba0f-615eafedc09f&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315088.yaml b/culinary/purchase_items/walmart_10315088.yaml new file mode 100644 index 0000000..12fd7f2 --- /dev/null +++ b/culinary/purchase_items/walmart_10315088.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10315088 +ingredient_id: bread_crumbs +name: Great Value Italian Style Bread Crumbs, 15 oz +supplier_id: walmart +supplier_sku: '10315088' +status: active +package: + quantity: 15.0 + unit_id: ounce_mass +prices: +- amount: 1.22 + currency: USD + effective_at: '2026-07-24' + source: + source_type: supplier + url: https://www.walmart.com/orders/88855716573167287161?storePurchase=true&source=sco&comm-msg-id=d3f726a2-2156-3417-84ec-afb435624394&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315278.yaml b/culinary/purchase_items/walmart_10315278.yaml new file mode 100644 index 0000000..0d9ce71 --- /dev/null +++ b/culinary/purchase_items/walmart_10315278.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10315278 +ingredient_id: corn_syrup_light +name: Great Value Light Corn Syrup, 16 fl oz +supplier_id: walmart +supplier_sku: '10315278' +status: active +package: + quantity: 16.0 + unit_id: fluid_ounce_us +prices: +- amount: 2.54 + currency: USD + effective_at: '2026-04-02' + source: + source_type: supplier + url: https://www.walmart.com/orders/32212589644659780686?storePurchase=true&source=sco&comm-msg-id=bdd4f76a-52e7-39ff-864c-e9dbcb66dbac&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315395.yaml b/culinary/purchase_items/walmart_10315395.yaml new file mode 100644 index 0000000..e81c32c --- /dev/null +++ b/culinary/purchase_items/walmart_10315395.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_10315395 +ingredient_id: rice +name: Great Value Long Grain Enriched Rice, 5 lbs +supplier_id: walmart +supplier_sku: '10315395' +status: active +package: + quantity: 5.0 + unit_id: pound +prices: +- amount: 3.34 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 3.37 + currency: USD + effective_at: '2026-06-18' + source: + source_type: supplier + url: https://www.walmart.com/orders/88612451444653736606?storePurchase=true&source=sco&comm-msg-id=26ab35a8-99b5-3d24-b52c-6b50daf73389&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315402.yaml b/culinary/purchase_items/walmart_10315402.yaml new file mode 100644 index 0000000..e9d4dd6 --- /dev/null +++ b/culinary/purchase_items/walmart_10315402.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10315402 +ingredient_id: parmesan_cheese +name: Great Value Grated Parmesan Cheese, 8 oz Shaker +supplier_id: walmart +supplier_sku: '10315402' +status: active +package: + quantity: 8.0 + unit_id: ounce_mass +prices: +- amount: 2.98 + currency: USD + effective_at: '2026-07-29' + source: + source_type: supplier + url: https://www.walmart.com/orders/29788178867501257987?storePurchase=true&source=sco&comm-msg-id=072f19de-49e0-3870-9016-3b9bbfb104a3&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10315545.yaml b/culinary/purchase_items/walmart_10315545.yaml new file mode 100644 index 0000000..f6f1706 --- /dev/null +++ b/culinary/purchase_items/walmart_10315545.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_10315545 +ingredient_id: mustard_dijon +name: Great Value Dijon Mustard, 12 oz +supplier_id: walmart +supplier_sku: '10315545' +status: active +package: + quantity: 12.0 + unit_id: ounce_mass +prices: +- amount: 1.52 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 1.62 + currency: USD + effective_at: '2026-03-08' + source: + source_type: supplier + url: https://www.walmart.com/orders/21688008947903306989?storePurchase=true&source=sco&comm-msg-id=017fa976-0a9d-3270-bc68-81ce98b486f4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10403017.yaml b/culinary/purchase_items/walmart_10403017.yaml new file mode 100644 index 0000000..b17fb0e --- /dev/null +++ b/culinary/purchase_items/walmart_10403017.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10403017 +ingredient_id: flour_all_purpose +name: Great Value All-Purpose Enriched Bleached Wheat Flour, 5 lb Bag +supplier_id: walmart +supplier_sku: '10403017' +status: active +package: + quantity: 5.0 + unit_id: pound +prices: +- amount: 2.38 + currency: USD + effective_at: '2025-11-26' + source: + source_type: supplier + url: https://www.walmart.com/orders/45977486879540147585?storePurchase=true&source=sco&comm-msg-id=e85eccf7-1a2b-390f-b679-d4ee9c9ff6d4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10415230.yaml b/culinary/purchase_items/walmart_10415230.yaml new file mode 100644 index 0000000..16fcfaa --- /dev/null +++ b/culinary/purchase_items/walmart_10415230.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_10415230 +ingredient_id: tomato_crushed_in_juice +name: Great Value Crushed Tomatoes with Tomato Puree, 28 oz +supplier_id: walmart +supplier_sku: '10415230' +status: active +package: + quantity: 28.0 + unit_id: ounce_mass +prices: +- amount: 1.52 + currency: USD + effective_at: '2026-06-05' + source: + source_type: supplier + url: https://www.walmart.com/orders/45912437424651713656?storePurchase=true&source=sco&comm-msg-id=81470600-62e5-3738-ba25-90a477f07003&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 1.52 + currency: USD + effective_at: '2026-06-25' + source: + source_type: supplier + url: https://www.walmart.com/orders/82877804999326477529?storePurchase=true&source=sco&comm-msg-id=6a8c1ef1-de58-3dcd-a501-d1299acef844&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10415512.yaml b/culinary/purchase_items/walmart_10415512.yaml new file mode 100644 index 0000000..66f17c5 --- /dev/null +++ b/culinary/purchase_items/walmart_10415512.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10415512 +ingredient_id: tomato_puree +name: Great Value Tomato Puree, 29 oz +supplier_id: walmart +supplier_sku: '10415512' +status: active +package: + quantity: 29.0 + unit_id: ounce_mass +prices: +- amount: 1.84 + currency: USD + effective_at: '2026-05-22' + source: + source_type: supplier + url: https://www.walmart.com/orders/13143795191281716091?storePurchase=true&source=sco&comm-msg-id=6dba5f85-ceec-3dae-8383-05e0586000a4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10415519.yaml b/culinary/purchase_items/walmart_10415519.yaml new file mode 100644 index 0000000..f31ff60 --- /dev/null +++ b/culinary/purchase_items/walmart_10415519.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_10415519 +ingredient_id: tomato_paste +name: Great Value Tomato Paste, 6 oz +supplier_id: walmart +supplier_sku: '10415519' +status: active +package: + quantity: 6.0 + unit_id: ounce_mass +prices: +- amount: 0.86 + currency: USD + effective_at: '2026-06-17' + source: + source_type: supplier + url: https://www.walmart.com/orders/97212257424853309674?storePurchase=true&source=sco&comm-msg-id=04a1542b-1cad-30cf-bef9-ade362c68939&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 0.86 + currency: USD + effective_at: '2026-06-25' + source: + source_type: supplier + url: https://www.walmart.com/orders/82877804999326477529?storePurchase=true&source=sco&comm-msg-id=6a8c1ef1-de58-3dcd-a501-d1299acef844&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10448316.yaml b/culinary/purchase_items/walmart_10448316.yaml new file mode 100644 index 0000000..f40b3fe --- /dev/null +++ b/culinary/purchase_items/walmart_10448316.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10448316 +ingredient_id: salt +name: Great Value Iodized Salt, 26 oz +supplier_id: walmart +supplier_sku: '10448316' +status: active +package: + quantity: 26.0 + unit_id: ounce_mass +prices: +- amount: 0.67 + currency: USD + effective_at: '2024-10-27' + source: + source_type: supplier + url: https://www.walmart.com/orders/25669937759389032313?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10450119.yaml b/culinary/purchase_items/walmart_10450119.yaml new file mode 100644 index 0000000..8eeeecf --- /dev/null +++ b/culinary/purchase_items/walmart_10450119.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10450119 +ingredient_id: milk +name: Great Value Milk, 2% Reduced Fat, Half Gallon, 64 fl oz +supplier_id: walmart +supplier_sku: '10450119' +status: active +package: + quantity: 64.0 + unit_id: fluid_ounce_us +prices: +- amount: 2.5 + currency: USD + effective_at: '2026-06-17' + source: + source_type: supplier + url: https://www.walmart.com/orders/97212257424853309674?storePurchase=true&source=sco&comm-msg-id=04a1542b-1cad-30cf-bef9-ade362c68939&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10450340.yaml b/culinary/purchase_items/walmart_10450340.yaml new file mode 100644 index 0000000..c763577 --- /dev/null +++ b/culinary/purchase_items/walmart_10450340.yaml @@ -0,0 +1,37 @@ +schema_version: 2 +id: walmart_10450340 +ingredient_id: heavy_cream +name: Great Value Heavy Whipping Cream, 32 oz Carton +supplier_id: walmart +supplier_sku: '10450340' +status: active +package: + quantity: 32.0 + unit_id: ounce_mass +prices: +- amount: 5.67 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 4.83 + currency: USD + effective_at: '2026-06-03' + source: + source_type: supplier + url: https://www.walmart.com/orders/37555189313161207151?storePurchase=true&source=sco&comm-msg-id=e605353b-d866-3ff0-8a98-b737c01559d4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 4.74 + currency: USD + effective_at: '2026-08-08' + source: + source_type: supplier + url: https://www.walmart.com/orders/23769992985344078333?storePurchase=true&source=sco&comm-msg-id=c4d34476-32e4-3e79-ba0f-615eafedc09f&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10452370.yaml b/culinary/purchase_items/walmart_10452370.yaml new file mode 100644 index 0000000..dbcd46f --- /dev/null +++ b/culinary/purchase_items/walmart_10452370.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10452370 +ingredient_id: cheddar_cheese +name: Great Value Mild Cheddar Finely Shredded Cheese, 8 oz Bag +supplier_id: walmart +supplier_sku: '10452370' +status: active +package: + quantity: 8.0 + unit_id: ounce_mass +prices: +- amount: 1.97 + currency: USD + effective_at: '2026-08-02' + source: + source_type: supplier + url: https://www.walmart.com/orders/87755939553167268191?storePurchase=true&source=sco&comm-msg-id=1590de77-aa2e-3f8b-8e1d-0b9c6b804d3b&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10452376.yaml b/culinary/purchase_items/walmart_10452376.yaml new file mode 100644 index 0000000..06b3a71 --- /dev/null +++ b/culinary/purchase_items/walmart_10452376.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10452376 +ingredient_id: cheddar_cheese +name: Great Value Mild Cheddar Block Cheese, 16 oz Chunk +supplier_id: walmart +supplier_sku: '10452376' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 3.74 + currency: USD + effective_at: '2024-09-22' + source: + source_type: supplier + url: https://www.walmart.com/orders/95212854266613748616?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10452385.yaml b/culinary/purchase_items/walmart_10452385.yaml new file mode 100644 index 0000000..87cb446 --- /dev/null +++ b/culinary/purchase_items/walmart_10452385.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10452385 +ingredient_id: sharp_cheddar_cheese +name: Great Value Block Sharp Cheddar Cheese, 16 oz +supplier_id: walmart +supplier_sku: '10452385' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 3.58 + currency: USD + effective_at: '2026-06-03' + source: + source_type: supplier + url: https://www.walmart.com/orders/37555189313161207151?storePurchase=true&source=sco&comm-msg-id=e605353b-d866-3ff0-8a98-b737c01559d4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_10535480.yaml b/culinary/purchase_items/walmart_10535480.yaml new file mode 100644 index 0000000..b2d6423 --- /dev/null +++ b/culinary/purchase_items/walmart_10535480.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_10535480 +ingredient_id: vinegar_balsamic +name: Colavita Balsamic Vinegar of Modena IGP, 17 Fluid Ounce Bottle +supplier_id: walmart +supplier_sku: '10535480' +status: active +package: + quantity: 17.0 + unit_id: fluid_ounce_us +prices: +- amount: 4.22 + currency: USD + effective_at: '2026-07-24' + source: + source_type: supplier + url: https://www.walmart.com/orders/88855716573167287161?storePurchase=true&source=sco&comm-msg-id=d3f726a2-2156-3417-84ec-afb435624394&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_111156738.yaml b/culinary/purchase_items/walmart_111156738.yaml new file mode 100644 index 0000000..ad76387 --- /dev/null +++ b/culinary/purchase_items/walmart_111156738.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_111156738 +ingredient_id: italian_sausage +name: Bird Farm Italian Sausage, 16 oz. Roll +supplier_id: walmart +supplier_sku: '111156738' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 3.82 + currency: USD + effective_at: '2026-07-24' + source: + source_type: supplier + url: https://www.walmart.com/orders/88855716573167287161?storePurchase=true&source=sco&comm-msg-id=d3f726a2-2156-3417-84ec-afb435624394&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_12166183.yaml b/culinary/purchase_items/walmart_12166183.yaml new file mode 100644 index 0000000..3f19773 --- /dev/null +++ b/culinary/purchase_items/walmart_12166183.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_12166183 +ingredient_id: bbq_sauce_hickory_smoke +name: "Sweet Baby Ray's\xAE Hickory & Brown Sugar Barbecue Sauce 40 oz" +supplier_id: walmart +supplier_sku: '12166183' +status: active +package: + quantity: 40.0 + unit_id: ounce_mass +prices: +- amount: 3.98 + currency: USD + effective_at: '2025-11-19' + source: + source_type: supplier + url: https://www.walmart.com/orders/72204744266813941828?storePurchase=true&source=sco&comm-msg-id=cf221815-7bc1-3044-a446-ca98cdb149cf&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_12512024.yaml b/culinary/purchase_items/walmart_12512024.yaml new file mode 100644 index 0000000..c42b534 --- /dev/null +++ b/culinary/purchase_items/walmart_12512024.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_12512024 +ingredient_id: lemon_juice +name: Great Value Lemon 100% Juice, 32 fl oz +supplier_id: walmart +supplier_sku: '12512024' +status: active +package: + quantity: 32.0 + unit_id: fluid_ounce_us +prices: +- amount: 2.88 + currency: USD + effective_at: '2024-10-27' + source: + source_type: supplier + url: https://www.walmart.com/orders/25669937759389032313?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_13424766.yaml b/culinary/purchase_items/walmart_13424766.yaml new file mode 100644 index 0000000..a838a79 --- /dev/null +++ b/culinary/purchase_items/walmart_13424766.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_13424766 +ingredient_id: chipotle_pepper_adobo +name: "La Coste\xF1a Chipotle Peppers in Adobo Sauce, 7 oz" +supplier_id: walmart +supplier_sku: '13424766' +status: active +package: + quantity: 7.0 + unit_id: ounce_mass +prices: +- amount: 1.63 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_15136790.yaml b/culinary/purchase_items/walmart_15136790.yaml new file mode 100644 index 0000000..a408bc5 --- /dev/null +++ b/culinary/purchase_items/walmart_15136790.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_15136790 +ingredient_id: ground_beef_73_27_raw +name: 73% Lean / 27% Fat Ground Beef, 1 lb Roll, Fresh, All Natural* +supplier_id: walmart +supplier_sku: '15136790' +status: active +package: + quantity: 1.0 + unit_id: pound +prices: +- amount: 5.94 + currency: USD + effective_at: '2026-07-24' + source: + source_type: supplier + url: https://www.walmart.com/orders/88855716573167287161?storePurchase=true&source=sco&comm-msg-id=d3f726a2-2156-3417-84ec-afb435624394&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_15716793.yaml b/culinary/purchase_items/walmart_15716793.yaml new file mode 100644 index 0000000..7d9d826 --- /dev/null +++ b/culinary/purchase_items/walmart_15716793.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_15716793 +ingredient_id: white_chocolate +name: Great Value White Chocolate Baking Bar, 4 oz Box +supplier_id: walmart +supplier_sku: '15716793' +status: active +package: + quantity: 4.0 + unit_id: ounce_mass +prices: +- amount: 2.84 + currency: USD + effective_at: '2024-12-22' + source: + source_type: supplier + url: https://www.walmart.com/orders/52869262785383055373?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_19400150.yaml b/culinary/purchase_items/walmart_19400150.yaml new file mode 100644 index 0000000..f86514a --- /dev/null +++ b/culinary/purchase_items/walmart_19400150.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_19400150 +ingredient_id: parmesan_cheese +name: Great Value Grated Parmesan Cheese, 16 oz Bottle +supplier_id: walmart +supplier_sku: '19400150' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 5.48 + currency: USD + effective_at: '2024-10-27' + source: + source_type: supplier + url: https://www.walmart.com/orders/25669937759389032313?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_288194636.yaml b/culinary/purchase_items/walmart_288194636.yaml new file mode 100644 index 0000000..c426d67 --- /dev/null +++ b/culinary/purchase_items/walmart_288194636.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_288194636 +ingredient_id: semisweet_chocolate +name: Great Value Mini Semi-Sweet Chocolate Baking Chips, 12 oz Bag +supplier_id: walmart +supplier_sku: '288194636' +status: active +package: + quantity: 12.0 + unit_id: ounce_mass +prices: +- amount: 3.58 + currency: USD + effective_at: '2026-03-17' + source: + source_type: supplier + url: https://www.walmart.com/orders/45212490664656751676?storePurchase=true&source=sco&comm-msg-id=80472a52-a1ec-31be-afb2-d769681e3fd7&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_34186943.yaml b/culinary/purchase_items/walmart_34186943.yaml new file mode 100644 index 0000000..27787b7 --- /dev/null +++ b/culinary/purchase_items/walmart_34186943.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_34186943 +ingredient_id: cheddar_cheese +name: Great Value Mild Cheddar Block Cheese, 8 oz Chunk +supplier_id: walmart +supplier_sku: '34186943' +status: active +package: + quantity: 8.0 + unit_id: ounce_mass +prices: +- amount: 1.87 + currency: USD + effective_at: '2026-06-29' + source: + source_type: supplier + url: https://www.walmart.com/orders/59188434776500223977?storePurchase=true&source=sco&comm-msg-id=1f48343d-ae31-3bad-9da4-eb56c957ab2e&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_36120978.yaml b/culinary/purchase_items/walmart_36120978.yaml new file mode 100644 index 0000000..9f07229 --- /dev/null +++ b/culinary/purchase_items/walmart_36120978.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_36120978 +ingredient_id: mayonnaise +name: Kewpie Mayonnaise, Japanese Umami Style Mayo 17.64oz, Bottle Dispenser +supplier_id: walmart +supplier_sku: '36120978' +status: active +package: + quantity: 17.64 + unit_id: ounce_mass +prices: +- amount: 5.87 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_41592222.yaml b/culinary/purchase_items/walmart_41592222.yaml new file mode 100644 index 0000000..618609d --- /dev/null +++ b/culinary/purchase_items/walmart_41592222.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_41592222 +ingredient_id: cream_cheese +name: Great Value Cream Cheese Brick, 8 oz Block, 2 Pack +supplier_id: walmart +supplier_sku: '41592222' +status: active +package: + quantity: 8.0 + unit_id: ounce_mass +prices: +- amount: 2.97 + currency: USD + effective_at: '2026-06-03' + source: + source_type: supplier + url: https://www.walmart.com/orders/37555189313161207151?storePurchase=true&source=sco&comm-msg-id=e605353b-d866-3ff0-8a98-b737c01559d4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +- amount: 2.97 + currency: USD + effective_at: '2026-06-13' + source: + source_type: supplier + url: https://www.walmart.com/orders/69943682191083413050?storePurchase=true&source=sco&comm-msg-id=516ea6c2-9756-3a40-bba2-3b2b125a3d90&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_426222521.yaml b/culinary/purchase_items/walmart_426222521.yaml new file mode 100644 index 0000000..ca8f776 --- /dev/null +++ b/culinary/purchase_items/walmart_426222521.yaml @@ -0,0 +1,38 @@ +schema_version: 2 +id: walmart_426222521 +ingredient_id: butter_flavored_shortening +name: Crisco All-Vegetable Butter Flavor Vegetable Shortening Can, Shelf-Stable, 48 + oz +supplier_id: walmart +supplier_sku: '426222521' +status: active +package: + quantity: 48.0 + unit_id: ounce_mass +prices: +- amount: 8.18 + currency: USD + effective_at: '2024-10-27' + source: + source_type: supplier + url: https://www.walmart.com/orders/25669937759389032313?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 8.18 + currency: USD + effective_at: '2024-12-22' + source: + source_type: supplier + url: https://www.walmart.com/orders/52869262785383055373?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 7.97 + currency: USD + effective_at: '2026-06-13' + source: + source_type: supplier + url: https://www.walmart.com/orders/69943682191083413050?storePurchase=true&source=sco&comm-msg-id=516ea6c2-9756-3a40-bba2-3b2b125a3d90&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_43236036.yaml b/culinary/purchase_items/walmart_43236036.yaml new file mode 100644 index 0000000..67216d3 --- /dev/null +++ b/culinary/purchase_items/walmart_43236036.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_43236036 +ingredient_id: butter +name: Prairie Farms Unsalted Quarter Butter Sticks, 16 Oz., 4 Count +supplier_id: walmart +supplier_sku: '43236036' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 4.88 + currency: USD + effective_at: '2024-12-22' + source: + source_type: supplier + url: https://www.walmart.com/orders/52869262785383055373?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_44001602.yaml b/culinary/purchase_items/walmart_44001602.yaml new file mode 100644 index 0000000..5663d1e --- /dev/null +++ b/culinary/purchase_items/walmart_44001602.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_44001602 +ingredient_id: ground_beef_73_27_raw +name: 73% Lean / 27% Fat Ground Beef, 10 lb Roll, Fresh, All Natural* +supplier_id: walmart +supplier_sku: '44001602' +status: active +package: + quantity: 10.0 + unit_id: pound +prices: +- amount: 34.44 + currency: USD + effective_at: '2025-03-21' + source: + source_type: supplier + url: https://www.walmart.com/orders/07296959777909046718?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_55014398.yaml b/culinary/purchase_items/walmart_55014398.yaml new file mode 100644 index 0000000..e441dba --- /dev/null +++ b/culinary/purchase_items/walmart_55014398.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_55014398 +ingredient_id: garlic +name: Fresh Garlic Sleeve, 3 Count +supplier_id: walmart +supplier_sku: '55014398' +status: active +package: + quantity: 3.0 + unit_id: each +prices: +- amount: 1.68 + currency: USD + effective_at: '2025-04-13' + source: + source_type: supplier + url: https://www.walmart.com/orders/26788998784729214984?storePurchase=true&source=sco&comm-msg-id=e356fc76-64a7-36ba-9e14-af090a705238&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_664106906.yaml b/culinary/purchase_items/walmart_664106906.yaml new file mode 100644 index 0000000..ccd95ed --- /dev/null +++ b/culinary/purchase_items/walmart_664106906.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_664106906 +ingredient_id: cornstarch +name: Great Value Corn Starch, 16 oz +supplier_id: walmart +supplier_sku: '664106906' +status: active +package: + quantity: 16.0 + unit_id: ounce_mass +prices: +- amount: 1.92 + currency: USD + effective_at: '2026-03-08' + source: + source_type: supplier + url: https://www.walmart.com/orders/21688008947903306989?storePurchase=true&source=sco&comm-msg-id=017fa976-0a9d-3270-bc68-81ce98b486f4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_676979470.yaml b/culinary/purchase_items/walmart_676979470.yaml new file mode 100644 index 0000000..ff75a16 --- /dev/null +++ b/culinary/purchase_items/walmart_676979470.yaml @@ -0,0 +1,21 @@ +schema_version: 2 +id: walmart_676979470 +ingredient_id: garlic_powder +name: Great Value Garlic Powder, 3.4 oz +supplier_id: walmart +supplier_sku: '676979470' +status: active +package: + quantity: 3.4 + unit_id: ounce_mass +prices: +- amount: 1.0 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/purchase_items/walmart_705601418.yaml b/culinary/purchase_items/walmart_705601418.yaml new file mode 100644 index 0000000..3960a1f --- /dev/null +++ b/culinary/purchase_items/walmart_705601418.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: walmart_705601418 +ingredient_id: onion_powder +name: Great Value Onion Powder, 3.25 oz +supplier_id: walmart +supplier_sku: '705601418' +status: active +package: + quantity: 3.25 + unit_id: ounce_mass +prices: +- amount: 1.0 + currency: USD + effective_at: '2024-11-16' + source: + source_type: supplier + url: https://www.walmart.com/orders/80631816330251657232?storePurchase=true&source=sco + title: Walmart receipt + reviewed: true +- amount: 1.08 + currency: USD + effective_at: '2026-03-08' + source: + source_type: supplier + url: https://www.walmart.com/orders/21688008947903306989?storePurchase=true&source=sco&comm-msg-id=017fa976-0a9d-3270-bc68-81ce98b486f4&comm-msg-vehicle=sms&comm-msg-recipient=eyJ2YWx1ZSI6IjE2NjAyMDIzNDkzIiwic3RyYXRlZ3kiOjAsImlzb19jYyI6bnVsbH0= + title: Walmart receipt + reviewed: true +nutrition_mapping_ids: [] +allergen_mapping_ids: [] diff --git a/culinary/recipes/alkaline_soy_meat_marinade.yaml b/culinary/recipes/alkaline_soy_meat_marinade.yaml new file mode 100644 index 0000000..d60a280 --- /dev/null +++ b/culinary/recipes/alkaline_soy_meat_marinade.yaml @@ -0,0 +1,60 @@ +schema_version: 2 +id: alkaline_soy_meat_marinade +revision: 1 +status: draft +title: Alkaline Soy Meat Marinade +categories: +- sauce +tags: +- marinade +- chicken +yield: + amount: + quantity: 107.48 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 6.38 + unit_id: gram + percentage: 6.38 + - id: line_03_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix until dissolved. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/amorosos_roll.yaml b/culinary/recipes/amorosos_roll.yaml new file mode 100644 index 0000000..be5f806 --- /dev/null +++ b/culinary/recipes/amorosos_roll.yaml @@ -0,0 +1,84 @@ +schema_version: 2 +id: amorosos_roll +revision: 1 +status: draft +title: Amoroso's Roll +categories: +- bread +tags: +- roll +- copycat +- amorosos +yield: + amount: + quantity: 172.4 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_04_wheat_gluten_70_80 + reference: + ingredient_id: wheat_gluten_70_80 + amount: + quantity: 3.1 + unit_id: gram + percentage: 3.1 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/apricot_glaze.yaml b/culinary/recipes/apricot_glaze.yaml new file mode 100644 index 0000000..ee40904 --- /dev/null +++ b/culinary/recipes/apricot_glaze.yaml @@ -0,0 +1,85 @@ +schema_version: 2 +id: apricot_glaze +revision: 1 +status: draft +title: Apricot Glaze +categories: +- sauce +tags: +- glaze +yield: + amount: + quantity: 304.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_apricot_jam + reference: + ingredient_id: apricot_jam + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 68 + unit_id: gram + percentage: 68 + - id: line_04_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 32 + unit_id: gram + percentage: 32 + - id: line_05_gelatin_granulated + reference: + ingredient_id: gelatin + amount: + quantity: 4.1 + unit_id: gram + percentage: 4.1 +equipment_ids: +- saucepan +steps: +- id: step_01 + order: 1 + instruction: Bloom gelatin in cold water, then melt. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine syrup, lemon juice, jam in saucepan and boil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Blend in melted gelatin. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Cool glaze to 75 °F, strain and use immediately. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/auntie_annes_pretzels.yaml b/culinary/recipes/auntie_annes_pretzels.yaml new file mode 100644 index 0000000..e83b96d --- /dev/null +++ b/culinary/recipes/auntie_annes_pretzels.yaml @@ -0,0 +1,134 @@ +schema_version: 2 +id: auntie_annes_pretzels +revision: 1 +status: draft +title: Auntie Anne's Pretzels +categories: +- bread +tags: +- pretzel +- copycat +- auntie-annes +yield: + amount: + quantity: 170 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 55 + unit_id: gram + percentage: 55 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 11 + unit_id: gram + percentage: 11 + - id: line_04_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- mixing_bowl +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Combine all and mix to full gluten development. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Press dough into 13 in x 9 in x 2 in pan. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Turn out onto parchment, covered. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Proof 30 min at 70 °F. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Cut into 16 strips, each 9 in long (achieved by halving 4 times). + component_ids: + - main +- id: step_06 + order: 6 + instruction: Submerge dough strips in alkaline bath for about 10 s. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Drain on wire mesh for about 10 s. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Transfer dough strip to parchment-lined sheet pan (handling should naturally elongate dough + to fit a half size sheet pan lengthwise). + component_ids: + - main +- id: step_09 + order: 9 + instruction: Apply salt. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Cut into 1 in pieces. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Bake 8 min at 500 °F. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Separate nuggets. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Combine nuggets and melted butter in bowl, toss until coated. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/bagel.yaml b/culinary/recipes/bagel.yaml new file mode 100644 index 0000000..f6bd819 --- /dev/null +++ b/culinary/recipes/bagel.yaml @@ -0,0 +1,68 @@ +schema_version: 2 +id: bagel +revision: 1 +status: draft +title: Bagel +categories: +- bread +tags: +- bagel +yield: + amount: + quantity: 160.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 56 + unit_id: gram + percentage: 56 + - id: line_03_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_barley_malt_powder + reference: + ingredient_id: barley_malt_powder + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/baileys_sourdough.yaml b/culinary/recipes/baileys_sourdough.yaml new file mode 100644 index 0000000..c5f0381 --- /dev/null +++ b/culinary/recipes/baileys_sourdough.yaml @@ -0,0 +1,173 @@ +schema_version: 2 +id: baileys_sourdough +revision: 1 +status: draft +title: Bailey's Sourdough +categories: +- bread +tags: +- sourdough +- loaf +yield: + amount: + quantity: 197 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_03_sourdough_starter + reference: + recipe_id: sourdough_starter + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- oven +- whisk +steps: +- id: step_01 + order: 1 + instruction: Mix water and starter, whisk. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add bread flour and salt. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix into shaggy dough. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Cover dough with damp towel and sit for 30 min. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Fold dough and rest for 30 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Repeat previous step 3 more times. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Place dough in straight sided vessel and allow to double in size, 8-10 hr. + component_ids: + - main +- id: step_08 + order: 8 + instruction: After dough doubles in size, shape the dough. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Pull dough into rectangle, fold over both vertical sides and roll dough up from bottom + to top. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Work the dough into a ball, adding tension as you move the dough back and forth. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Allow dough to rest for 30 min. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Work the dough one more time into a ball with a smooth top. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Line banneton with cloth and sprinkle with corn meal, flour, and rice flour. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Place dough in banneton, seam side up. + component_ids: + - main +- id: step_15 + order: 15 + instruction: Place banneton in plastic grocery bag and place in refrigerator for 1-24 hr. + component_ids: + - main +- id: step_16 + order: 16 + instruction: Set oven to 550 °F and preheat dutch oven. + component_ids: + - main +- id: step_17 + order: 17 + instruction: Once oven is preheated, take out dough, place on strip of parchment, and mark with ×. + component_ids: + - main +- id: step_18 + order: 18 + instruction: Put dough in preheated dutch oven, reduce oven temp to 450 °F, and bake dough in dutch + oven for 30 min. + component_ids: + - main +- id: step_19 + order: 19 + instruction: After 30 min, take bread out of dutch oven, place on rack of oven, and reduce temp to 425 + °F. + component_ids: + - main +- id: step_20 + order: 20 + instruction: Bake for additional 10-15 min. + component_ids: + - main +- id: step_21 + order: 21 + instruction: Take bread out of oven and place on cooling rack. + component_ids: + - main +- id: step_22 + order: 22 + instruction: Do not cut until fully cooled / room temp. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/banana_bread.yaml b/culinary/recipes/banana_bread.yaml new file mode 100644 index 0000000..4ae85c6 --- /dev/null +++ b/culinary/recipes/banana_bread.yaml @@ -0,0 +1,117 @@ +schema_version: 2 +id: banana_bread +revision: 1 +status: draft +title: Banana Bread +categories: +- dessert +tags: +- quick-bread +- banana +yield: + amount: + quantity: 369.85 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 58 + unit_id: gram + percentage: 58 + - id: line_04_banana + reference: + ingredient_id: banana + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_05_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_06_walnut + reference: + ingredient_id: walnut + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1.25 + unit_id: gram + percentage: 1.25 + - id: line_09_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 +steps: +- id: step_01 + order: 1 + instruction: Combine, mix dry. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine, mix wet. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add liquid to dry. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix only until flour just moistened. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Bake immediately, 50 min at 375 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/beer_cheese.yaml b/culinary/recipes/beer_cheese.yaml new file mode 100644 index 0000000..15acd82 --- /dev/null +++ b/culinary/recipes/beer_cheese.yaml @@ -0,0 +1,133 @@ +schema_version: 2 +id: beer_cheese +revision: 1 +status: draft +title: Beer Cheese +categories: +- sauce +tags: +- dip +- cheese +yield: + amount: + quantity: 281.09 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_white_cheddar_parmesan_blend + reference: + recipe_id: white_cheddar_parmesan_blend + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_03_beer + reference: + ingredient_id: beer + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 13 + unit_id: gram + percentage: 13 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 12.5 + unit_id: gram + percentage: 12.5 + - id: line_06_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 2.2 + unit_id: gram + percentage: 2.2 + - id: line_07_sodium_citrate + reference: + ingredient_id: sodium_citrate + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_09_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.13 + unit_id: gram + percentage: 0.13 + - id: line_10_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.13 + unit_id: gram + percentage: 0.13 + - id: line_11_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.13 + unit_id: gram + percentage: 0.13 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine, dissolve cold! water, beer, milk powder, corn starch, sodium citrate. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Heat to simmer (205+ °F). + component_ids: + - main +- id: step_03 + order: 3 + instruction: Remove from heat. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix in cheese, in small pieces, one at a time. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add oil, whisk smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/benihana_yum_yum_sauce.yaml b/culinary/recipes/benihana_yum_yum_sauce.yaml new file mode 100644 index 0000000..f58937e --- /dev/null +++ b/culinary/recipes/benihana_yum_yum_sauce.yaml @@ -0,0 +1,125 @@ +schema_version: 2 +id: benihana_yum_yum_sauce +revision: 1 +status: draft +title: Benihana Yum Yum Sauce +categories: +- sauce +tags: +- copycat +- benihana +yield: + amount: + quantity: 204.49 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 57 + unit_id: gram + percentage: 57 + - id: line_03_butter_flavored_shortening + reference: + ingredient_id: butter_flavored_shortening + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_04_ketchup + reference: + ingredient_id: ketchup + amount: + quantity: 11 + unit_id: gram + percentage: 11 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 9 + unit_id: gram + percentage: 9 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_07_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.66 + unit_id: gram + percentage: 0.66 + - id: line_08_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 + - id: line_09_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.33 + unit_id: gram + percentage: 0.33 +equipment_ids: +- mixing_bowl +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine mayonnaise, whipping cream, ketchup. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine spices. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Melt shortening in bowl. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add all to shortening bowl. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Whisk until smooth. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Refridgerate overnight. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/berry_bagel.yaml b/culinary/recipes/berry_bagel.yaml new file mode 100644 index 0000000..07a1402 --- /dev/null +++ b/culinary/recipes/berry_bagel.yaml @@ -0,0 +1,151 @@ +schema_version: 2 +id: berry_bagel +revision: 1 +status: draft +title: Berry Bagel +categories: +- bread +tags: +- bagel +yield: + amount: + quantity: 173.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 44 + unit_id: gram + percentage: 44 + - id: line_03_berries + reference: + recipe_id: blueberry_raspberry_blend + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_05_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_06_barley_malt_syrup + reference: + ingredient_id: barley_malt_syrup + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 1.85 + unit_id: gram + percentage: 1.85 + - id: line_09_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 1.25 + unit_id: gram + percentage: 1.25 +steps: +- id: step_01 + order: 1 + instruction: Combine ingredients (minus berries and oil) and mix until dough comes together. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add oil and continue mixing until smooth dough forms. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add frozen blueberries and mix roughly for 1 min until combined. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Proof until almost double. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Divide into 5 portions and roll in tight balls. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Rest for 15 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Shape into bagels. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Proof until double. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Boil pot of water with 1 tbsp malted barley syrup. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Boil each bagel for 10-20 seconds on both sides. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Drain bagels and place on parchment paper. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Bake at 410 °F for 15-20 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/berry_muffin.yaml b/culinary/recipes/berry_muffin.yaml new file mode 100644 index 0000000..b894358 --- /dev/null +++ b/culinary/recipes/berry_muffin.yaml @@ -0,0 +1,123 @@ +schema_version: 2 +id: berry_muffin +revision: 1 +status: draft +title: Berry Muffin +categories: +- dessert +tags: +- muffin +yield: + amount: + quantity: 362 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 70 + unit_id: gram + percentage: 70 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 63 + unit_id: gram + percentage: 63 + - id: line_04_shortening + reference: + ingredient_id: shortening + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_05_frozen_berries + reference: + recipe_id: blueberry_raspberry_blend + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_07_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_10_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 +steps: +- id: step_01 + order: 1 + instruction: Sift together dry. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine all liquid. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add liquid to dry. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix until just moistened, lumpy. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Pan and bake immediately. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/blueberry_raspberry_blend.yaml b/culinary/recipes/blueberry_raspberry_blend.yaml new file mode 100644 index 0000000..83bee40 --- /dev/null +++ b/culinary/recipes/blueberry_raspberry_blend.yaml @@ -0,0 +1,46 @@ +schema_version: 2 +id: blueberry_raspberry_blend +revision: 1 +status: active +title: Blueberry–Raspberry Blend +categories: +- component +tags: +- fruit +- berry +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_blueberry + reference: + ingredient_id: blueberry + amount: + quantity: 50 + unit_id: gram + percentage: 50 + basis_member: true + - id: line_02_raspberry + reference: + ingredient_id: raspberry + amount: + quantity: 50 + unit_id: gram + percentage: 50 +steps: +- id: step_01 + order: 1 + instruction: Combine equal weights of blueberries and raspberries. + component_ids: + - main diff --git a/culinary/recipes/broccoli_cheddar_soup.yaml b/culinary/recipes/broccoli_cheddar_soup.yaml new file mode 100644 index 0000000..bfc07a2 --- /dev/null +++ b/culinary/recipes/broccoli_cheddar_soup.yaml @@ -0,0 +1,222 @@ +schema_version: 2 +id: broccoli_cheddar_soup +revision: 1 +status: draft +title: Broccoli Cheddar Soup +categories: +- soup +tags: +- cheese +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 20 + unit_id: gram + percentage: 20 + basis_member: true + - id: line_02_onion + reference: + ingredient_id: onion_yellow + amount: + quantity: 10 + unit_id: gram + percentage: 10 + basis_member: true + - id: line_03_carrot + reference: + ingredient_id: carrot + amount: + quantity: 10 + unit_id: gram + percentage: 10 + basis_member: true + - id: line_04_butter + reference: + ingredient_id: butter + amount: + quantity: 1.2 + unit_id: gram + percentage: 1.2 + basis_member: true + - id: line_05_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 2 + unit_id: gram + percentage: 2 + basis_member: true + - id: line_06_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 1 + unit_id: gram + percentage: 1 + basis_member: true + - id: line_07_sharp_cheddar_cheese + reference: + ingredient_id: sharp_cheddar_cheese + amount: + quantity: 11 + unit_id: gram + percentage: 11 + basis_member: true + - id: line_08_raw_broccoli + reference: + ingredient_id: raw_broccoli + amount: + quantity: 20 + unit_id: gram + percentage: 20 + basis_member: true + - id: line_09_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 12 + unit_id: gram + percentage: 12 + basis_member: true + - id: line_10_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.225 + unit_id: gram + percentage: 0.225 + basis_member: true + - id: line_11_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.05 + unit_id: gram + percentage: 0.05 + basis_member: true + - id: line_12_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + basis_member: true + - id: line_13_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + basis_member: true + - id: line_14_nutmeg + reference: + ingredient_id: nutmeg + amount: + quantity: 0.025 + unit_id: gram + percentage: 0.025 + basis_member: true + - id: line_15_bacon + reference: + ingredient_id: bacon + amount: + quantity: 12 + unit_id: gram + percentage: 12 + basis_member: true +steps: +- id: step_01 + order: 1 + instruction: Dice the bacon. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Cook the bacon in a pot. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Drain and reserve the bacon. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Return the bacon fat to the pot. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add the butter, diced onion, paprika, cayenne, garlic, and black pepper. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Cook until the onion softens. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add the flour. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Cook the flour mixture briefly. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Add the water and chicken base. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Add the broccoli and carrot. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Cook for about 20 min, or until the vegetables are tender. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Add the bacon and heavy cream. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Add the cheddar a little at a time. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Stir until the cheese melts. + component_ids: + - main +- id: step_15 + order: 15 + instruction: Add the nutmeg. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/buttercream.yaml b/culinary/recipes/buttercream.yaml new file mode 100644 index 0000000..b284e22 --- /dev/null +++ b/culinary/recipes/buttercream.yaml @@ -0,0 +1,85 @@ +schema_version: 2 +id: buttercream +revision: 1 +status: draft +title: Buttercream +categories: +- sauce +tags: +- icing +yield: + amount: + quantity: 168.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 7.5 + unit_id: gram + percentage: 7.5 + - id: line_05_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_06_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 +steps: +- id: step_01 + order: 1 + instruction: Using paddle attachment, cream together butter, shortening, sugar until well-blended. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add liquids, blend on medium. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Blend in more liquid for softer buttercream. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/buttermilk_biscuits.yaml b/culinary/recipes/buttermilk_biscuits.yaml new file mode 100644 index 0000000..a8c1696 --- /dev/null +++ b/culinary/recipes/buttermilk_biscuits.yaml @@ -0,0 +1,137 @@ +schema_version: 2 +id: buttermilk_biscuits +revision: 1 +status: draft +title: Buttermilk Biscuits +categories: +- bread +tags: +- biscuit +yield: + amount: + quantity: 213 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_buttermilk + reference: + ingredient_id: buttermilk + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 35 + unit_id: gram + percentage: 35 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Scale. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Sift, combine dry. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine liquid. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Paddle in shortening into dry until coarse cornmeal. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add liquid to dry. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Mix until just combined, soft dough. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Fold 6x. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Roll out 1/2 in thick. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Cut into shapes. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Place 1/2 in apart parchment paper. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Egg wash (optional). + component_ids: + - main +- id: step_12 + order: 12 + instruction: Bake immediately, 15-20 min at 400 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/caramel_sauce.yaml b/culinary/recipes/caramel_sauce.yaml new file mode 100644 index 0000000..d741161 --- /dev/null +++ b/culinary/recipes/caramel_sauce.yaml @@ -0,0 +1,120 @@ +schema_version: 2 +id: caramel_sauce +revision: 1 +status: draft +title: Caramel Sauce +categories: +- sauce +tags: +- dessert-sauce +- caramel +yield: + amount: + quantity: 227.04 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sugar + reference: + ingredient_id: sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 38.6 + unit_id: gram + percentage: 38.6 + - id: line_03_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 36 + unit_id: gram + percentage: 36 + - id: line_04_water + reference: + ingredient_id: water + amount: + quantity: 26.8 + unit_id: gram + percentage: 26.8 + - id: line_05_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 18.6 + unit_id: gram + percentage: 18.6 + - id: line_06_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 4.54 + unit_id: gram + percentage: 4.54 + - id: line_07_kosher_salt + reference: + ingredient_id: salt + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 +equipment_ids: +- saucepan +steps: +- id: step_01 + order: 1 + instruction: In saucepan, combine water, sugar, corn syrup. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix well. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add medium heat. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Stir until sugar dissolves and liquid is clear. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Only swirl henceforth to prevent crystals. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Once begin to color, swirl often to prevent local caramelization. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Heat to ≈390 °F, dark golden, until first whisps of smoke. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Halt cooking immediately, remove from heat. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/caramelized_onion.yaml b/culinary/recipes/caramelized_onion.yaml new file mode 100644 index 0000000..a044db9 --- /dev/null +++ b/culinary/recipes/caramelized_onion.yaml @@ -0,0 +1,102 @@ +schema_version: 2 +id: caramelized_onion +revision: 1 +status: draft +title: Caramelized Onion +categories: +- side +tags: +- onion +yield: + amount: + quantity: 115.8 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_onion_raw + reference: + ingredient_id: onion_yellow + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 + - id: line_06_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_07_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 +steps: +- id: step_01 + order: 1 + instruction: Slice onions to consistent thickness. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine all ingredients. + component_ids: + - main +- id: step_03 + order: 3 + instruction: 'Add to rice cooker: use rice cooker function.' + component_ids: + - main +- id: step_04 + order: 4 + instruction: Allow onions to cook until cooking function completes. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Finish caramelization using slow cooker function or cooking in a pan, stirring often. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/carrot_soup.yaml b/culinary/recipes/carrot_soup.yaml new file mode 100644 index 0000000..74a4b6e --- /dev/null +++ b/culinary/recipes/carrot_soup.yaml @@ -0,0 +1,72 @@ +schema_version: 2 +id: carrot_soup +revision: 1 +status: draft +title: Carrot Soup +categories: +- soup +tags: [] +yield: + amount: + quantity: 167.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_carrot + reference: + ingredient_id: carrot + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 35 + unit_id: gram + percentage: 35 + - id: line_03_butter + reference: + ingredient_id: butter + amount: + quantity: 31 + unit_id: gram + percentage: 31 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_05_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +steps: +- id: step_01 + order: 1 + instruction: Cook in pressure cooker. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cheese_danish_filling.yaml b/culinary/recipes/cheese_danish_filling.yaml new file mode 100644 index 0000000..a907e6b --- /dev/null +++ b/culinary/recipes/cheese_danish_filling.yaml @@ -0,0 +1,87 @@ +schema_version: 2 +id: cheese_danish_filling +revision: 1 +status: draft +title: Cheese Danish Filling +categories: +- pastry +tags: +- filling +yield: + amount: + quantity: 155.84 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 16.9 + unit_id: gram + percentage: 16.9 + - id: line_04_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 12.5 + unit_id: gram + percentage: 12.5 + - id: line_05_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_06_lemon_zest + reference: + ingredient_id: lemon_zest + amount: + quantity: 0.22 + unit_id: gram + percentage: 0.22 + - id: line_07_orange_zest + reference: + ingredient_id: orange_zest + amount: + quantity: 0.22 + unit_id: gram + percentage: 0.22 +steps: +- id: step_01 + order: 1 + instruction: Paddle mix medium all except eggs, until light, smooth. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add egg gradually, scraping periodically until blended. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cheesecake.yaml b/culinary/recipes/cheesecake.yaml new file mode 100644 index 0000000..ef1f175 --- /dev/null +++ b/culinary/recipes/cheesecake.yaml @@ -0,0 +1,157 @@ +schema_version: 2 +id: cheesecake +revision: 1 +status: draft +title: Cheesecake +categories: +- dessert +tags: +- cake +yield: + amount: + quantity: 181.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 26.2 + unit_id: gram + percentage: 26.2 + - id: line_04_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 8.7 + unit_id: gram + percentage: 8.7 + - id: line_05_sour_cream + reference: + ingredient_id: sour_cream + amount: + quantity: 8.7 + unit_id: gram + percentage: 8.7 + - id: line_06_butter + reference: + ingredient_id: butter + amount: + quantity: 4.8 + unit_id: gram + percentage: 4.8 + - id: line_07_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 1.9 + unit_id: gram + percentage: 1.9 + - id: line_08_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.9 + unit_id: gram + percentage: 0.9 +equipment_ids: +- oven +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Grease, parchment 8 in pan. + component_ids: + - main +- id: step_02 + order: 2 + instruction: 1/4 in thick crust. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Paddle cream cheese til smooth. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add butter, sugar. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix medium til smooth, scrape. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add lemon juice, vanilla. mix low, scrape. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add eggs at 3 stages, scrape. + component_ids: + - main +- id: step_08 + order: 8 + instruction: After smooth, add heavy cream, sour cream. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Place batter in pan (935 g / cake). + component_ids: + - main +- id: step_10 + order: 10 + instruction: Place pan on sheet pan filled with water. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Bake 50 min at 325 °F, middle. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Crack oven to cool to about 135. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Move to wire rack to cool to room temp. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Cover, refrigerate. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chick_fil_a_sauce.yaml b/culinary/recipes/chick_fil_a_sauce.yaml new file mode 100644 index 0000000..f7d47c9 --- /dev/null +++ b/culinary/recipes/chick_fil_a_sauce.yaml @@ -0,0 +1,64 @@ +schema_version: 2 +id: chick_fil_a_sauce +revision: 1 +status: draft +title: Chick-fil-A Sauce +categories: +- sauce +tags: +- copycat +- chick-fil-a +yield: + amount: + quantity: 188.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_bbq_sauce_hickory_smoke + reference: + ingredient_id: bbq_sauce_hickory_smoke + amount: + quantity: 62 + unit_id: gram + percentage: 62 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 17 + unit_id: gram + percentage: 17 + - id: line_04_mustard_yellow + reference: + ingredient_id: mustard_yellow + amount: + quantity: 9.5 + unit_id: gram + percentage: 9.5 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine all with whisk. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chicken_sausage.yaml b/culinary/recipes/chicken_sausage.yaml new file mode 100644 index 0000000..67152f8 --- /dev/null +++ b/culinary/recipes/chicken_sausage.yaml @@ -0,0 +1,155 @@ +schema_version: 2 +id: chicken_sausage +revision: 1 +status: draft +title: Chicken Sausage +categories: +- meat +tags: +- chicken +- sausage +yield: + amount: + quantity: 136.95 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_chicken_breast + reference: + ingredient_id: chicken_breast + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water_ice + reference: + ingredient_id: water_ice + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1.3 + unit_id: gram + percentage: 1.3 + - id: line_06_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_07_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_08_msg + reference: + ingredient_id: msg + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_09_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_10_coriander + reference: + ingredient_id: coriander + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_11_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 + - id: line_12_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 + - id: line_13_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +steps: +- id: step_01 + order: 1 + instruction: Chill meat to 32 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Cut chicken breast to size. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Grind large. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add salt. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Grind small. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Season. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Mix spiral. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chicken_velvet.yaml b/culinary/recipes/chicken_velvet.yaml new file mode 100644 index 0000000..60e74b4 --- /dev/null +++ b/culinary/recipes/chicken_velvet.yaml @@ -0,0 +1,105 @@ +schema_version: 2 +id: chicken_velvet +revision: 1 +status: draft +title: Chicken Velvet +categories: +- meat +tags: +- chicken +- marinade +yield: + amount: + quantity: 104.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_chicken + reference: + ingredient_id: chicken_breast + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_03_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_04_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_06_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_08_msg + reference: + ingredient_id: msg + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 +steps: +- id: step_01 + order: 1 + instruction: Rinse chicken slivers under cold water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Wring out water thoroughly. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix in baking soda. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix in rest of ingredients. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chilis_avocado_ranch.yaml b/culinary/recipes/chilis_avocado_ranch.yaml new file mode 100644 index 0000000..d8f9bf5 --- /dev/null +++ b/culinary/recipes/chilis_avocado_ranch.yaml @@ -0,0 +1,57 @@ +schema_version: 2 +id: chilis_avocado_ranch +revision: 1 +status: draft +title: Chili's Avocado Ranch +categories: +- sauce +tags: +- dressing +- ranch +- copycat +- chilis +yield: + amount: + quantity: 156.7 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_ranch + reference: + ingredient_id: ranch + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_guacamole + reference: + recipe_id: guacamole + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 6.7 + unit_id: gram + percentage: 6.7 +steps: +- id: step_01 + order: 1 + instruction: Blend. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chipotle_pinto_beans.yaml b/culinary/recipes/chipotle_pinto_beans.yaml new file mode 100644 index 0000000..edc2ae0 --- /dev/null +++ b/culinary/recipes/chipotle_pinto_beans.yaml @@ -0,0 +1,134 @@ +schema_version: 2 +id: chipotle_pinto_beans +revision: 1 +status: draft +title: Chipotle Pinto Beans +categories: +- side +tags: +- beans +yield: + amount: + quantity: 146.86 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_pinto_beans_dry_uncooked + reference: + ingredient_id: pinto_beans_dry_uncooked + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 4.5 + unit_id: gram + percentage: 4.5 + - id: line_04_chipotle_pepper_adobo + reference: + ingredient_id: chipotle_pepper_adobo + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_05_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 3.33 + unit_id: gram + percentage: 3.33 + - id: line_06_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 3.33 + unit_id: gram + percentage: 3.33 + - id: line_07_onion_mince_dry + reference: + ingredient_id: onion_dehydrated_flake + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_09_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_10_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_11_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_12_oregano_marjoram + reference: + recipe_id: dominos_oregano_marjoram_blend + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Cook and drain beans. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine all beans in blender. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Blend until smooth. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Stir in mixture into drained, cooked beans. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chocolate_biscotti.yaml b/culinary/recipes/chocolate_biscotti.yaml new file mode 100644 index 0000000..bbf0b44 --- /dev/null +++ b/culinary/recipes/chocolate_biscotti.yaml @@ -0,0 +1,167 @@ +schema_version: 2 +id: chocolate_biscotti +revision: 1 +status: draft +title: Chocolate Biscotti +categories: +- dessert +tags: +- cookie +- chocolate +yield: + amount: + quantity: 353.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 82 + unit_id: gram + percentage: 82 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 78 + unit_id: gram + percentage: 78 + - id: line_04_chocolate_chunks_chopped + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 70 + unit_id: gram + percentage: 70 + notes: chopped into chunks + - id: line_05_cocoa_powder + reference: + ingredient_id: cocoa_powder + amount: + quantity: 16 + unit_id: gram + percentage: 16 + - id: line_06_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 2.1 + unit_id: gram + percentage: 2.1 + - id: line_08_espresso_powder + reference: + ingredient_id: espresso_powder + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_10_almond_extract + reference: + ingredient_id: almond_extract + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 +equipment_ids: +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Line sheet pan with parchment paper. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Sift flour, baking soda, cocoa powder. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whip eggs, sugar, vanilla, almond extract and salt high until thick and light, ≈5 min. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix in sifted dry at low speed until just incorporated. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Fold in chocolate and (almonds). + component_ids: + - main +- id: step_06 + order: 6 + instruction: Form dough into strip on sheet pan. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Bake 300 °F 50 min. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Remove to cool 10 min. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Cut slices 1/2 in. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Bake 12 min at 275 °F. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Flip. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Bake 12 min at 275 °F. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Cooling rack, cool completely. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chocolate_chip_cookie.yaml b/culinary/recipes/chocolate_chip_cookie.yaml new file mode 100644 index 0000000..93e4da9 --- /dev/null +++ b/culinary/recipes/chocolate_chip_cookie.yaml @@ -0,0 +1,153 @@ +schema_version: 2 +id: chocolate_chip_cookie +revision: 1 +status: draft +title: Chocolate Chip Cookie +categories: +- dessert +tags: +- cookie +- chocolate +yield: + amount: + quantity: 414.11 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_chocolate_chip + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 110.53 + unit_id: gram + percentage: 110.53 + notes: chips + - id: line_03_butter + reference: + ingredient_id: butter + amount: + quantity: 70.79 + unit_id: gram + percentage: 70.79 + - id: line_04_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 52.63 + unit_id: gram + percentage: 52.63 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 44.21 + unit_id: gram + percentage: 44.21 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 31.58 + unit_id: gram + percentage: 31.58 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1.68 + unit_id: gram + percentage: 1.68 + - id: line_08_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1.58 + unit_id: gram + percentage: 1.58 + - id: line_09_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1.11 + unit_id: gram + percentage: 1.11 +steps: +- id: step_01 + order: 1 + instruction: Cream butter, sugar. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Gradually add eggs. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add vanilla. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine bread flour, baking soda. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to 50% incorporation. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add chocolate chips. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Mix until just incorporated. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Roll into 17 in log. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Wrap in parchment, refrigerate. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Cut to 100 g portions. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Place on parchment sheet pans. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Bake 380 °F 10-12 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chocolate_ganache.yaml b/culinary/recipes/chocolate_ganache.yaml new file mode 100644 index 0000000..f3f6d5b --- /dev/null +++ b/culinary/recipes/chocolate_ganache.yaml @@ -0,0 +1,53 @@ +schema_version: 2 +id: chocolate_ganache +revision: 1 +status: draft +title: Chocolate Ganache +categories: +- sauce +tags: +- dessert-sauce +- chocolate +yield: + amount: + quantity: 205 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_dark_chocolate + reference: + ingredient_id: dark_chocolate + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 105 + unit_id: gram + percentage: 105 +steps: +- id: step_01 + order: 1 + instruction: Heat heavy cream to 100 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Pour over chocolate chips, stirring. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/chow_mein_sauce.yaml b/culinary/recipes/chow_mein_sauce.yaml new file mode 100644 index 0000000..0e817b9 --- /dev/null +++ b/culinary/recipes/chow_mein_sauce.yaml @@ -0,0 +1,103 @@ +schema_version: 2 +id: chow_mein_sauce +revision: 1 +status: draft +title: Chow Mein Sauce +categories: +- sauce +tags: +- chinese +yield: + amount: + quantity: 343.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 52 + unit_id: gram + percentage: 52 + - id: line_03_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 52 + unit_id: gram + percentage: 52 + - id: line_04_water + reference: + ingredient_id: water + amount: + quantity: 52 + unit_id: gram + percentage: 52 + - id: line_05_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 35 + unit_id: gram + percentage: 35 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 27.6 + unit_id: gram + percentage: 27.6 + - id: line_07_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_09_msg + reference: + ingredient_id: msg + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_10_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Combine all. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cilantro_lime_rice.yaml b/culinary/recipes/cilantro_lime_rice.yaml new file mode 100644 index 0000000..418f4e9 --- /dev/null +++ b/culinary/recipes/cilantro_lime_rice.yaml @@ -0,0 +1,104 @@ +schema_version: 2 +id: cilantro_lime_rice +revision: 1 +status: draft +title: Cilantro Lime Rice +categories: +- side +tags: +- rice +yield: + amount: + quantity: 245.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_rice + reference: + ingredient_id: rice + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 125 + unit_id: gram + percentage: 125 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_04_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 4.25 + unit_id: gram + percentage: 4.25 + - id: line_05_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 4.25 + unit_id: gram + percentage: 4.25 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2.25 + unit_id: gram + percentage: 2.25 + - id: line_07_cilantro_chopped + reference: + ingredient_id: cilantro + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + prep: + - action_id: chop +steps: +- id: step_01 + order: 1 + instruction: Rinse rice cold water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Cook rice. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine salt, cilantro, lemon & lime juice. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Stir until salt dissolves. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Pour seasoning liquid on rice, stir. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cinnamon_crunch_bagel.yaml b/culinary/recipes/cinnamon_crunch_bagel.yaml new file mode 100644 index 0000000..a20cf2f --- /dev/null +++ b/culinary/recipes/cinnamon_crunch_bagel.yaml @@ -0,0 +1,82 @@ +schema_version: 2 +id: cinnamon_crunch_bagel +revision: 1 +status: draft +title: Cinnamon Crunch Bagel +categories: +- bread +tags: +- bagel +yield: + amount: + quantity: 212.75 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_03_white_chocolate + reference: + ingredient_id: white_chocolate + amount: + quantity: 39 + unit_id: gram + percentage: 39 + - id: line_04_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_05_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cinnamon_filling.yaml b/culinary/recipes/cinnamon_filling.yaml new file mode 100644 index 0000000..4fc25ab --- /dev/null +++ b/culinary/recipes/cinnamon_filling.yaml @@ -0,0 +1,82 @@ +schema_version: 2 +id: cinnamon_filling +revision: 1 +status: draft +title: Cinnamon Filling +categories: +- component +tags: +- filling +yield: + amount: + quantity: 191.3 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_shortening + reference: + ingredient_id: shortening + amount: + quantity: 36.4 + unit_id: gram + percentage: 36.4 + - id: line_03_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 27.3 + unit_id: gram + percentage: 27.3 + - id: line_04_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 13.6 + unit_id: gram + percentage: 13.6 + - id: line_05_cocoa_powder + reference: + ingredient_id: cocoa_powder + amount: + quantity: 3.6 + unit_id: gram + percentage: 3.6 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 1.4 + unit_id: gram + percentage: 1.4 + - id: line_07_water + reference: + ingredient_id: water + amount: + quantity: 9 + unit_id: gram + percentage: 9 +steps: +- id: step_01 + order: 1 + instruction: Mix the ingredients until combined. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cinnamon_roll.yaml b/culinary/recipes/cinnamon_roll.yaml new file mode 100644 index 0000000..0eb4337 --- /dev/null +++ b/culinary/recipes/cinnamon_roll.yaml @@ -0,0 +1,199 @@ +schema_version: 2 +id: cinnamon_roll +revision: 1 +status: draft +title: Cinnamon Roll +categories: +- bread +tags: +- roll +- sweet dough +yield: + amount: + quantity: 225.77 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_tangzhong + reference: + recipe_id: tangzhong + amount: + quantity: 38.3 + unit_id: gram + percentage: 38.3 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 41.6 + unit_id: gram + percentage: 41.6 + - id: line_04_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 16 + unit_id: gram + percentage: 16 + - id: line_06_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 12.8 + unit_id: gram + percentage: 12.8 + - id: line_07_shortening + reference: + ingredient_id: shortening + amount: + quantity: 6.4 + unit_id: gram + percentage: 6.4 + - id: line_08_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2.6 + unit_id: gram + percentage: 2.6 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 1.9 + unit_id: gram + percentage: 1.9 + - id: line_10_lecithin_powder + reference: + ingredient_id: lecithin_powder + amount: + quantity: 0.67 + unit_id: gram + percentage: 0.67 + - id: line_11_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +equipment_ids: +- mixing_bowl +- stand_mixer +steps: +- id: step_01 + order: 1 + instruction: Add the water, corn syrup, sugar, and tangzhong to the mixer bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix until the tangzhong disperses. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the flour, lecithin powder, and baking powder. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix until no dry flour remains. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Rest the dough for 10-20 minutes to hydrate. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add the salt and yeast. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Mix with the dough hook until the dough starts to become smooth and elastic. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Add the shortening. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Mix until the shortening is fully incorporated. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Stream in the oil slowly while mixing. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Mix until the dough is smooth, soft, and extensible. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Refrigerate the dough as needed to keep it below 78 F. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Cover the dough and bulk ferment it in the refrigerator until noticeably puffy. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Degas the dough gently. + component_ids: + - main +- id: step_15 + order: 15 + instruction: Roll, fill, shape, and pan the dough. + component_ids: + - main +- id: step_16 + order: 16 + instruction: Proof the rolls until very puffy and the dough springs back slowly when pressed. + component_ids: + - main +- id: step_17 + order: 17 + instruction: Bake the rolls at 350 F for at least 22 minutes, until set and lightly browned. + component_ids: + - main +- id: step_18 + order: 18 + instruction: Cool the rolls briefly before icing. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cinnamon_sugar.yaml b/culinary/recipes/cinnamon_sugar.yaml new file mode 100644 index 0000000..a61dca3 --- /dev/null +++ b/culinary/recipes/cinnamon_sugar.yaml @@ -0,0 +1,54 @@ +schema_version: 2 +id: cinnamon_sugar +revision: 1 +status: draft +title: Cinnamon Sugar +categories: +- component +tags: +- seasoning +yield: + amount: + quantity: 206 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sugar + reference: + ingredient_id: sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_03_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 6 + unit_id: gram + percentage: 6 +steps: +- id: step_01 + order: 1 + instruction: Mix + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/crab_rangoon.yaml b/culinary/recipes/crab_rangoon.yaml new file mode 100644 index 0000000..a134a50 --- /dev/null +++ b/culinary/recipes/crab_rangoon.yaml @@ -0,0 +1,123 @@ +schema_version: 2 +id: crab_rangoon +revision: 1 +status: draft +title: Crab Rangoon +categories: +- side +tags: +- seafood +- filling +yield: + amount: + quantity: 134.9 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_imitation_crab_minced + reference: + ingredient_id: imitation_crab + amount: + quantity: 18 + unit_id: gram + percentage: 18 + prep: + - action_id: mince + - id: line_03_scallion_minced + reference: + ingredient_id: green_onion + amount: + quantity: 11 + unit_id: gram + percentage: 11 + prep: + - action_id: mince + - id: line_04_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1.7 + unit_id: gram + percentage: 1.7 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 0.62 + unit_id: gram + percentage: 0.62 + - id: line_07_msg + reference: + ingredient_id: msg + amount: + quantity: 0.45 + unit_id: gram + percentage: 0.45 + - id: line_08_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 0.45 + unit_id: gram + percentage: 0.45 + - id: line_09_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_10_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.18 + unit_id: gram + percentage: 0.18 +steps: +- id: step_01 + order: 1 + instruction: Mix all into room temp cream cheese. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Refrigerate. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Form into balls. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Freeze balls. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cream_cheese_icing.yaml b/culinary/recipes/cream_cheese_icing.yaml new file mode 100644 index 0000000..d14b9aa --- /dev/null +++ b/culinary/recipes/cream_cheese_icing.yaml @@ -0,0 +1,71 @@ +schema_version: 2 +id: cream_cheese_icing +revision: 1 +status: draft +title: Cream Cheese Icing +categories: +- sauce +tags: +- icing +yield: + amount: + quantity: 161 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_04_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 +steps: +- id: step_01 + order: 1 + instruction: Paddle cream cheese, sugar until well blended. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add liquids, blend on medium until light, fluffy. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Blend in more liquid for softer buttercream. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cream_cheese_icing_2.yaml b/culinary/recipes/cream_cheese_icing_2.yaml new file mode 100644 index 0000000..9a0d2bf --- /dev/null +++ b/culinary/recipes/cream_cheese_icing_2.yaml @@ -0,0 +1,128 @@ +schema_version: 2 +id: cream_cheese_icing_2 +revision: 1 +status: draft +title: Cream Cheese Icing 2 +categories: +- sauce +tags: +- icing +- frosting +yield: + amount: + quantity: 347.4 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 212 + unit_id: gram + percentage: 212 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_04_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 3.25 + unit_id: gram + percentage: 3.25 + - id: line_05_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 6.5 + unit_id: gram + percentage: 6.5 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 0.35 + unit_id: gram + percentage: 0.35 + - id: line_07_butter_extract + reference: + ingredient_id: butter_extract + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +steps: +- id: step_01 + order: 1 + instruction: Soften the cream cheese to cool room temperature, about 60°F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Beat the shortening until smooth and slightly aerated. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the cream cheese. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Beat until uniform and smooth. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add the confectioners' sugar in 2 to 3 additions. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Mix on low speed after each confectioners' sugar addition. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Beat on medium speed until smooth. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Add the salt, vanilla extract, corn syrup, and butter extract. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Mix until spreadable or slow-flowing. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Beat for 15 to 30 seconds to finish. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/creamed_berry_muffin.yaml b/culinary/recipes/creamed_berry_muffin.yaml new file mode 100644 index 0000000..b508c04 --- /dev/null +++ b/culinary/recipes/creamed_berry_muffin.yaml @@ -0,0 +1,143 @@ +schema_version: 2 +id: creamed_berry_muffin +revision: 1 +status: draft +title: Creamed Berry Muffin +categories: +- dessert +tags: +- muffin +yield: + amount: + quantity: 388.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_04_shortening + reference: + ingredient_id: shortening + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_05_frozen_berries + reference: + recipe_id: blueberry_raspberry_blend + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_07_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_10_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 +steps: +- id: step_01 + order: 1 + instruction: Cobine fat, sugar, salt, spices, milk powder. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Paddle mix until light. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add eggs in 2 to 3 stages, cream well between stages. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Sift in dry ingredients. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Stir together liquid until combined. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add sifted dry alternately with liquids. + component_ids: + - main +- id: step_07 + order: 7 + instruction: 1/4 dry -- mix until just blended. + component_ids: + - main +- id: step_08 + order: 8 + instruction: 1/3 liquid -- mix until just blended. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Repeat, scrape, done. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/creamed_chocolate_chip_muffin.yaml b/culinary/recipes/creamed_chocolate_chip_muffin.yaml new file mode 100644 index 0000000..f8353c6 --- /dev/null +++ b/culinary/recipes/creamed_chocolate_chip_muffin.yaml @@ -0,0 +1,145 @@ +schema_version: 2 +id: creamed_chocolate_chip_muffin +revision: 1 +status: draft +title: Creamed Chocolate Chip Muffin +categories: +- dessert +tags: +- muffin +- chocolate +yield: + amount: + quantity: 329.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_shortening + reference: + ingredient_id: shortening + amount: + quantity: 90 + unit_id: gram + percentage: 90 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_05_chocolate_chip + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 30 + unit_id: gram + percentage: 30 + notes: chips + - id: line_06_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_07_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 1.25 + unit_id: gram + percentage: 1.25 + - id: line_10_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1.25 + unit_id: gram + percentage: 1.25 +steps: +- id: step_01 + order: 1 + instruction: Cobine fat, sugar, salt, spices, milk powder. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Paddle mix until light. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add eggs in 2 to 3 stages, cream well between stages. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Sift in dry ingredients. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Stir together liquid until combined. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add sifted dry alternately with liquids. + component_ids: + - main +- id: step_07 + order: 7 + instruction: 1/4 dry -- mix until just blended. + component_ids: + - main +- id: step_08 + order: 8 + instruction: 1/3 liquid -- mix until just blended. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Repeat, scrape, done. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/cuban_mustard_mayo.yaml b/culinary/recipes/cuban_mustard_mayo.yaml new file mode 100644 index 0000000..2b06116 --- /dev/null +++ b/culinary/recipes/cuban_mustard_mayo.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: cuban_mustard_mayo +revision: 1 +status: draft +title: Cuban Mustard Mayo +categories: +- sauce +tags: +- spread +yield: + amount: + quantity: 133 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_mustard + reference: + ingredient_id: mustard_yellow + amount: + quantity: 33 + unit_id: gram + percentage: 33 +steps: +- id: step_01 + order: 1 + instruction: Mix. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dark_espresso_brownie.yaml b/culinary/recipes/dark_espresso_brownie.yaml new file mode 100644 index 0000000..6bba9aa --- /dev/null +++ b/culinary/recipes/dark_espresso_brownie.yaml @@ -0,0 +1,156 @@ +schema_version: 2 +id: dark_espresso_brownie +revision: 1 +status: draft +title: Dark Espresso Brownie +categories: +- dessert +tags: +- brownie +- chocolate +yield: + amount: + quantity: 1256.8 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 360 + unit_id: gram + percentage: 360 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 272 + unit_id: gram + percentage: 272 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 236 + unit_id: gram + percentage: 236 + - id: line_05_dark_chocolate + reference: + ingredient_id: dark_chocolate + amount: + quantity: 136 + unit_id: gram + percentage: 136 + - id: line_06_dark_cocoa_powder + reference: + ingredient_id: dark_cocoa_powder + amount: + quantity: 92 + unit_id: gram + percentage: 92 + - id: line_07_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 44 + unit_id: gram + percentage: 44 + - id: line_08_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 3.2 + unit_id: gram + percentage: 3.2 + - id: line_10_espresso_powder + reference: + ingredient_id: espresso_powder + amount: + quantity: 1.6 + unit_id: gram + percentage: 1.6 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine sugar, brown sugar, salt, egg, vanilla, espresso powder. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Sift together flour, cocoa powder. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Melt fat and chocolate. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Whisk egg mix on high until thick, ≈8 min. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add chocolate,oil - mix low. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add flour, cocoa - mix low. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Final mix by hand, folding with spatula. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Grease 13 in × 9 in × 2 in cake pan, line with parchment. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Pour in batter, level. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Bake 30 min at 350 °F. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Cool. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dinner_rolls.yaml b/culinary/recipes/dinner_rolls.yaml new file mode 100644 index 0000000..8cacb3b --- /dev/null +++ b/culinary/recipes/dinner_rolls.yaml @@ -0,0 +1,136 @@ +schema_version: 2 +id: dinner_rolls +revision: 1 +status: draft +title: Dinner Rolls +categories: +- bread +tags: +- roll +yield: + amount: + quantity: 197.25 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 55 + unit_id: gram + percentage: 55 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 5.25 + unit_id: gram + percentage: 5.25 + - id: line_07_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine, whisk dry ingredients. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine, whisk wet except shortening. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix 5 min until well combined. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add shortening. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to ≈25 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Shape into balls. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Arrange on greased, optionally parchment-lined 13 × 9 pan. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Proof ≈2 hr at 80 °F, covered. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Egg wash. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Bake ≈22 min at 350 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_cheddar_cheese_blend.yaml b/culinary/recipes/dominos_cheddar_cheese_blend.yaml new file mode 100644 index 0000000..931ef10 --- /dev/null +++ b/culinary/recipes/dominos_cheddar_cheese_blend.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: dominos_cheddar_cheese_blend +revision: 1 +status: testing +title: Domino's-Style Cheddar Cheese Blend +summary: A home-scale approximation of Domino's proprietary cheddar and pizza-cheese blend. +categories: [component] +tags: [cheese, copycat, dominos] +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100 + unit_id: gram +components: +- id: main + name: Cheese blend + items: + - id: cheddar + reference: + ingredient_id: cheddar_cheese + amount: + quantity: 60 + unit_id: gram + percentage: 60 + basis_member: true + - id: pizza_cheese + reference: + ingredient_id: mozzarella_cheese + amount: + quantity: 40 + unit_id: gram + percentage: 40 + basis_member: true +steps: +- id: combine + order: 1 + instruction: Shred both cheeses to the same size and toss until evenly distributed. + component_ids: [main] + item_ids: [cheddar, pizza_cheese] +notes: +- Domino's identifies cheddar before pizza cheese in its ingredient declaration but does not publish their ratio; 60/40 is an explicit working estimate. +- Commercial anti-caking starches, cellulose, preservatives, and the modified ingredients in Domino's Pizza Cheese are omitted from this fresh home-scale blend. diff --git a/culinary/recipes/dominos_garlic_oil_blend.yaml b/culinary/recipes/dominos_garlic_oil_blend.yaml new file mode 100644 index 0000000..b44616d --- /dev/null +++ b/culinary/recipes/dominos_garlic_oil_blend.yaml @@ -0,0 +1,113 @@ +schema_version: 2 +id: dominos_garlic_oil_blend +revision: 1 +status: draft +title: Domino's Garlic Oil Blend +categories: +- sauce +tags: +- copycat +- dominos +- pizza +yield: + amount: + quantity: 124.45 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_butter_flavored_shortening + reference: + ingredient_id: butter_flavored_shortening + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_canola_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_03_parmesan_cheese + reference: + ingredient_id: parmesan_cheese + amount: + quantity: 5.6 + unit_id: gram + percentage: 5.6 + - id: line_04_garlic_dehydrated + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 5.6 + unit_id: gram + percentage: 5.6 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 4.65 + unit_id: gram + percentage: 4.65 + - id: line_06_parsley + reference: + ingredient_id: parsley + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 +equipment_ids: +- oven +steps: +- id: step_01 + order: 1 + instruction: Grind the dehydrated garlic to a fine, even powder if it is coarse or granulated. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Thoroughly combine the garlic, Parmesan, and salt. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Warm the butter-flavored shortening and butter-flavored oil together to 45–50 °C (113–122 + °F), stirring just until the shortening is fully melted. + component_ids: + - main +- id: step_04 + order: 4 + instruction: While whisking or blending continuously, gradually add the dry mixture to the warm fat. + Continue mixing until no clumps remain. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Let stand for 10 minutes to bloom the dehydrated garlic, stirring once or twice to keep + the solids suspended. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Stir in the parsley. Keep the blend warm enough to remain fluid and stir immediately before + use. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Brush a thin, even layer onto the crust immediately after the pizza leaves the oven. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_oregano_marjoram_blend.yaml b/culinary/recipes/dominos_oregano_marjoram_blend.yaml new file mode 100644 index 0000000..33c66d7 --- /dev/null +++ b/culinary/recipes/dominos_oregano_marjoram_blend.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: dominos_oregano_marjoram_blend +revision: 1 +status: draft +title: Domino's-Style Oregano–Marjoram Blend +categories: +- component +tags: +- herb-blend +- dominos +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_oregano + reference: + ingredient_id: oregano + amount: + quantity: 50 + unit_id: gram + percentage: 50 + basis_member: true + - id: line_02_marjoram + reference: + ingredient_id: marjoram + amount: + quantity: 50 + unit_id: gram + percentage: 50 +steps: +- id: step_01 + order: 1 + instruction: Combine the dried oregano and dried marjoram evenly. + component_ids: + - main +notes: +- Domino's identifies its shake-on blend as oregano and marjoram but does not publish the ratio; 50:50 is an explicit provisional formulation. diff --git a/culinary/recipes/dominos_pizza.yaml b/culinary/recipes/dominos_pizza.yaml new file mode 100644 index 0000000..7b4c209 --- /dev/null +++ b/culinary/recipes/dominos_pizza.yaml @@ -0,0 +1,114 @@ +schema_version: 2 +id: dominos_pizza +revision: 1 +status: draft +title: Domino's Pizza Dough +categories: +- bread +tags: +- pizza +- copycat +- dominos +yield: + amount: + quantity: 169.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3.9 + unit_id: gram + percentage: 3.9 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +equipment_ids: +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Add water, then dry ingredients to mixing bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix until dough is halfway developed. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add oil slowly. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix to full gluten development. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Divide. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Shape into ball. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Lightly oil ball. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Store in air-tight container, refrigerate. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_pizza_sauce.yaml b/culinary/recipes/dominos_pizza_sauce.yaml new file mode 100644 index 0000000..7c58713 --- /dev/null +++ b/culinary/recipes/dominos_pizza_sauce.yaml @@ -0,0 +1,72 @@ +schema_version: 2 +id: dominos_pizza_sauce +revision: 1 +status: draft +title: Domino's Pizza Sauce +categories: +- sauce +tags: +- pizza +- copycat +- dominos +yield: + amount: + quantity: 107.7 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_paste + reference: + ingredient_id: tomato_paste + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_03_salt + reference: + ingredient_id: salt + amount: + quantity: 2.7 + unit_id: gram + percentage: 2.7 + - id: line_04_spice_blend + reference: + ingredient_id: spice_blend + amount: + quantity: 1.6 + unit_id: gram + percentage: 1.6 + - id: line_05_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Whisk to combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_pizza_sauce_v2.yaml b/culinary/recipes/dominos_pizza_sauce_v2.yaml new file mode 100644 index 0000000..199c319 --- /dev/null +++ b/culinary/recipes/dominos_pizza_sauce_v2.yaml @@ -0,0 +1,149 @@ +schema_version: 2 +id: dominos_pizza_sauce_v2 +revision: 1 +status: draft +title: Domino's Pizza Sauce V2 +categories: +- sauce +tags: +- pizza +- copycat +- dominos +yield: + amount: + quantity: 284.91 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_paste + reference: + ingredient_id: tomato_paste + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 172.35 + unit_id: gram + percentage: 172.35 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 6.94 + unit_id: gram + percentage: 6.94 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_05_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.82 + unit_id: gram + percentage: 0.82 + - id: line_06_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.49 + unit_id: gram + percentage: 0.49 + - id: line_07_basil + reference: + ingredient_id: basil + amount: + quantity: 0.22 + unit_id: gram + percentage: 0.22 + - id: line_08_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.22 + unit_id: gram + percentage: 0.22 + - id: line_09_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 0.68 + unit_id: gram + percentage: 0.68 + - id: line_10_citric_acid + reference: + ingredient_id: citric_acid + amount: + quantity: 0.16 + unit_id: gram + percentage: 0.16 + - id: line_11_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.03 + unit_id: gram + percentage: 0.03 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Reserve 15% of the water and whisk the remainder into the tomato paste until smooth. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk in the reserved water. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Grind the oregano and basil to a fine powder. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add the sugar, salt, garlic powder, oregano, basil, black pepper, citric acid, and cayenne. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Blend for 20–30 seconds. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add the oil and blend briefly. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Cover and refrigerate for 12–24 hours. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Apply cold; do not precook. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_pizza_sauce_v3.yaml b/culinary/recipes/dominos_pizza_sauce_v3.yaml new file mode 100644 index 0000000..8b121dd --- /dev/null +++ b/culinary/recipes/dominos_pizza_sauce_v3.yaml @@ -0,0 +1,156 @@ +schema_version: 2 +id: dominos_pizza_sauce_v3 +revision: 1 +status: draft +title: Domino's Pizza Sauce V3 +categories: +- sauce +tags: +- pizza +- copycat +- dominos +yield: + amount: + quantity: 254.11 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_paste + reference: + ingredient_id: tomato_paste + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 141.18 + unit_id: gram + percentage: 141.18 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 6.35 + unit_id: gram + percentage: 6.35 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 3.18 + unit_id: gram + percentage: 3.18 + - id: line_05_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 1.06 + unit_id: gram + percentage: 1.06 + - id: line_06_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.65 + unit_id: gram + percentage: 0.65 + - id: line_07_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.32 + unit_id: gram + percentage: 0.32 + - id: line_08_basil + reference: + ingredient_id: basil + amount: + quantity: 0.21 + unit_id: gram + percentage: 0.21 + - id: line_09_marjoram + reference: + ingredient_id: marjoram + amount: + quantity: 0.21 + unit_id: gram + percentage: 0.21 + - id: line_10_soybean_oil + reference: + ingredient_id: soybean_oil + amount: + quantity: 0.65 + unit_id: gram + percentage: 0.65 + - id: line_11_citric_acid + reference: + ingredient_id: citric_acid + amount: + quantity: 0.24 + unit_id: gram + percentage: 0.24 + - id: line_12_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.06 + unit_id: gram + percentage: 0.06 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Reserve 15% of the water and whisk the remainder into the tomato paste until smooth. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk in the reserved water. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Grind the oregano and basil to a fine powder. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add the sugar, salt, garlic powder, oregano, basil, black pepper, citric acid, and cayenne. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Blend for 20–30 seconds. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add the oil and blend briefly. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Cover and refrigerate for 12–24 hours. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Apply cold; do not precook. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/dominos_stuffed_cheesy_bread.yaml b/culinary/recipes/dominos_stuffed_cheesy_bread.yaml new file mode 100644 index 0000000..34fee95 --- /dev/null +++ b/culinary/recipes/dominos_stuffed_cheesy_bread.yaml @@ -0,0 +1,115 @@ +schema_version: 2 +id: dominos_stuffed_cheesy_bread +revision: 1 +status: draft +title: Domino's Stuffed Cheesy Bread +categories: +- bread +tags: +- bread +- cheese +- copycat +- dominos +yield: + amount: + quantity: 156.08 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_dominos_pizza_dough + reference: + recipe_id: dominos_pizza + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_mozzarella_cheese + reference: + ingredient_id: mozzarella_cheese + amount: + quantity: 20.4 + unit_id: gram + percentage: 20.4 + - id: line_03_cheddar_cheese_blend + reference: + recipe_id: dominos_cheddar_cheese_blend + amount: + quantity: 30.58 + unit_id: gram + percentage: 30.58 + - id: line_04_dominos_garlic_oil_blend + reference: + recipe_id: dominos_garlic_oil_blend + amount: + quantity: 5.1 + unit_id: gram + percentage: 5.1 +equipment_ids: +- oven +steps: +- id: step_01 + order: 1 + instruction: Bring one properly proofed 556 g, 14-inch Domino's Pizza dough ball to its normal shaping + temperature. Lightly coat it with cornmeal. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Stretch and flatten the dough into a 16 × 10 inch (41 × 25 cm) rectangle, squaring the + edges. Do not form a rim. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Cut the rectangle across the center into two 8 × 10 inch (20 × 25 cm) rectangles. Each + 278 g rectangle makes one eight-piece bread. Place each on parchment paper over a pizza screen or + perforated pizza pan. + component_ids: + - main +- id: step_04 + order: 4 + instruction: On each rectangle, distribute 56.7 g pizza cheese edge to edge over one 4 × 10 inch half. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Fold the uncovered half over the cheese, matching the corners and edges. Do not crimp or + roll the perimeter. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Make seven evenly spaced crosswise cuts through both layers, producing eight attached portions. + Make the center cut first, halve each side, and then halve each quarter. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Distribute 85.0 g cheddar cheese blend evenly from edge to edge over the top. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Bake until the bottom is golden brown, the dough is baked through, and the topping is evenly + melted. In a home oven, start with 475 °F (245 °C) on a thoroughly preheated screen or perforated + pan and begin checking at 10 minutes; use color and doneness rather than time alone. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Immediately apply 14.2 g warm garlic oil blend, first around the perimeter and then in + a zigzag across the center. Serve on the parchment. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/donuts.yaml b/culinary/recipes/donuts.yaml new file mode 100644 index 0000000..dc958cb --- /dev/null +++ b/culinary/recipes/donuts.yaml @@ -0,0 +1,150 @@ +schema_version: 2 +id: donuts +revision: 1 +status: draft +title: Donuts +categories: +- dessert +tags: +- fried +yield: + amount: + quantity: 200.21 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 18.8 + unit_id: gram + percentage: 18.8 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 12.4 + unit_id: gram + percentage: 12.4 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 6.5 + unit_id: gram + percentage: 6.5 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 6.5 + unit_id: gram + percentage: 6.5 + - id: line_07_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2.21 + unit_id: gram + percentage: 2.21 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + - id: line_10_mace_nutmeg + reference: + ingredient_id: mace_nutmeg + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +equipment_ids: +- stand_mixer +steps: +- id: step_01 + order: 1 + instruction: Add water, egg, sugar, milk, baking powder, salt, nutmeg to mixer. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add flours, yeast, mix, conditioner. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix until well incorporated. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add shortening. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix until intense stage gluten development. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Proof 1 hr, until roughly doubled. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Sheet to 0.5 in. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Cut donuts with 3 in donut cutter. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Proof ≈45 min at 80 °F 65% rh on parchment. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Fry 2 min per side at 350-365 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/egg_noodle.yaml b/culinary/recipes/egg_noodle.yaml new file mode 100644 index 0000000..d4dda71 --- /dev/null +++ b/culinary/recipes/egg_noodle.yaml @@ -0,0 +1,61 @@ +schema_version: 2 +id: egg_noodle +revision: 1 +status: draft +title: Egg Noodle +categories: +- side +tags: +- noodle +yield: + amount: + quantity: 164.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 12.5 + unit_id: gram + percentage: 12.5 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/egg_replacer.yaml b/culinary/recipes/egg_replacer.yaml new file mode 100644 index 0000000..797241f --- /dev/null +++ b/culinary/recipes/egg_replacer.yaml @@ -0,0 +1,68 @@ +schema_version: 2 +id: egg_replacer +revision: 1 +status: draft +title: Egg Replacer +categories: +- component +tags: +- base-formula +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 65 + unit_id: gram + percentage: 65 + basis_member: true + - id: line_02_tapioca_starch + reference: + ingredient_id: tapioca_starch + amount: + quantity: 18.5 + unit_id: gram + percentage: 18.5 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_04_liquid_sunflower_lecithin + reference: + ingredient_id: liquid_sunflower_lecithin + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/english_muffin.yaml b/culinary/recipes/english_muffin.yaml new file mode 100644 index 0000000..f69d077 --- /dev/null +++ b/culinary/recipes/english_muffin.yaml @@ -0,0 +1,124 @@ +schema_version: 2 +id: english_muffin +revision: 1 +status: draft +title: English Muffin +categories: +- bread +tags: +- muffin +yield: + amount: + quantity: 186.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_04_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_05_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine, whisk dry ingredients. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine, whisk wet except shortening. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix 5 min until well combined. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add shortening. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to ≈25 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Divide ≈85 g ball. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Proof 1 hr at 77 °F. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Bake 350 °F baking steel. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Flip 3x. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/focaccia.yaml b/culinary/recipes/focaccia.yaml new file mode 100644 index 0000000..a245664 --- /dev/null +++ b/culinary/recipes/focaccia.yaml @@ -0,0 +1,127 @@ +schema_version: 2 +id: focaccia +revision: 1 +status: draft +title: Focaccia +categories: +- bread +tags: +- loaf +yield: + amount: + quantity: 197 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 85 + unit_id: gram + percentage: 85 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_barley_malt_syrup + reference: + ingredient_id: barley_malt_syrup + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Preheat baking steel 45 min, 500 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine dry. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine liquid. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix until well combined. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add fat. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Intensive mix. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Flatten into oiled 1/2 sheet pan. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Allow proof ≈1 hr, 80 °F. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Stripple dough halfway through proof. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Stripple once more at the end of proof. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Bake 12 min at 500 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/fried_rice.yaml b/culinary/recipes/fried_rice.yaml new file mode 100644 index 0000000..74f476c --- /dev/null +++ b/culinary/recipes/fried_rice.yaml @@ -0,0 +1,152 @@ +schema_version: 2 +id: fried_rice +revision: 1 +status: draft +title: Fried Rice +categories: +- side +tags: +- rice +- chinese +yield: + amount: + quantity: 309.93 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_rice_cooked + reference: + ingredient_id: rice_cooked + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_vegetables_mixed + reference: + ingredient_id: vegetables_mixed + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_bacon + reference: + ingredient_id: bacon + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_05_onion + reference: + ingredient_id: onion_yellow + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_06_green_onion + reference: + ingredient_id: green_onion + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_07_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_08_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_09_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_10_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_11_salt + reference: + ingredient_id: salt + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_12_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_13_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 0.08 + unit_id: gram + percentage: 0.08 +equipment_ids: +- skillet +steps: +- id: step_01 + order: 1 + instruction: Heat 1½ tbsp oil (wok) or 2 tbsp oil (skillet) over high heat until smoking. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add onion, garlic, bacon; cook ≈1½ min until bacon light golden. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add frozen vegetables; cook ≈2 min until thawed and moisture evaporates. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add rice and sauce; cook ≈1½ min until liquid evaporates. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Push rice aside; add ½ tbsp oil to empty space; add egg; scramble fully. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add green onion; mix egg into rice; remove from heat; serve immediately. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/general_tso_sauce.yaml b/culinary/recipes/general_tso_sauce.yaml new file mode 100644 index 0000000..7a5eba0 --- /dev/null +++ b/culinary/recipes/general_tso_sauce.yaml @@ -0,0 +1,138 @@ +schema_version: 2 +id: general_tso_sauce +revision: 1 +status: draft +title: General Tso's Sauce +categories: +- sauce +tags: +- chinese +yield: + amount: + quantity: 384 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 64 + unit_id: gram + percentage: 64 + - id: line_03_soy_sauce_light_low_sodium + reference: + ingredient_id: soy_sauce_light_low_sodium + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_05_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_06_vinegar_rice + reference: + ingredient_id: vinegar_rice + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_garlic_minced + reference: + ingredient_id: garlic + amount: + quantity: 20 + unit_id: gram + percentage: 20 + prep: + - action_id: mince + - id: line_08_ginger_minced + reference: + ingredient_id: ginger + amount: + quantity: 20 + unit_id: gram + percentage: 20 + prep: + - action_id: mince + - id: line_09_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 17 + unit_id: gram + percentage: 17 + - id: line_10_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_11_scallion + reference: + ingredient_id: green_onion + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_12_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_13_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 3 + unit_id: gram + percentage: 3 +steps: +- id: step_01 + order: 1 + instruction: Saute garlic, ginger. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Bring to boil, stirring vigorously until thickened slightly. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/ginger_molasses_cookie.yaml b/culinary/recipes/ginger_molasses_cookie.yaml new file mode 100644 index 0000000..6476216 --- /dev/null +++ b/culinary/recipes/ginger_molasses_cookie.yaml @@ -0,0 +1,146 @@ +schema_version: 2 +id: ginger_molasses_cookie +revision: 1 +status: draft +title: Ginger Molasses Cookie +categories: +- dessert +tags: +- cookie +yield: + amount: + quantity: 257.38 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 71.32 + unit_id: gram + percentage: 71.32 + - id: line_03_butter + reference: + ingredient_id: butter + amount: + quantity: 44.67 + unit_id: gram + percentage: 44.67 + - id: line_04_molasses + reference: + ingredient_id: molasses + amount: + quantity: 26.65 + unit_id: gram + percentage: 26.65 + - id: line_05_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 7.84 + unit_id: gram + percentage: 7.84 + - id: line_06_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 2.51 + unit_id: gram + percentage: 2.51 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_08_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.94 + unit_id: gram + percentage: 0.94 + - id: line_09_ginger + reference: + ingredient_id: ginger_ground + amount: + quantity: 0.94 + unit_id: gram + percentage: 0.94 + - id: line_10_cloves + reference: + ingredient_id: cloves + amount: + quantity: 0.63 + unit_id: gram + percentage: 0.63 + - id: line_11_nutmeg + reference: + ingredient_id: nutmeg + amount: + quantity: 0.47 + unit_id: gram + percentage: 0.47 + - id: line_12_allspice + reference: + ingredient_id: allspice + amount: + quantity: 0.31 + unit_id: gram + percentage: 0.31 +equipment_ids: +- oven +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Cream the butter and sugar until well combined. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add the eggs and then the molasses. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the dry ingredients and mix until well incorporated. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Scale into 2 lb 3 oz (1000 g) pieces and roll into 17 in (43 cm) logs (sheet pan width). + component_ids: + - main +- id: step_05 + order: 5 + instruction: Wrap each log in parchment, and refrigerate until ready to bake. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Cut to the desired size [2 oz (50 g) to 4 oz (100 g)], place on parchment-lined sheet pans, + and bake at 350 °F in a convection oven for 12 to 15 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/graham_cracker_crust.yaml b/culinary/recipes/graham_cracker_crust.yaml new file mode 100644 index 0000000..ace78f1 --- /dev/null +++ b/culinary/recipes/graham_cracker_crust.yaml @@ -0,0 +1,73 @@ +schema_version: 2 +id: graham_cracker_crust +revision: 1 +status: draft +title: Graham Cracker Crust +categories: +- pastry +tags: +- crust +yield: + amount: + quantity: 181.4 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_graham_cracker_crumbs + reference: + ingredient_id: graham_cracker + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + prep: + - action_id: crush + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 48.4 + unit_id: gram + percentage: 48.4 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 33 + unit_id: gram + percentage: 33 +equipment_ids: +- food_processor +steps: +- id: step_01 + order: 1 + instruction: Mix graham cracker crumbs and sugar in food processor. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Stir in melted butter. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix until crumbs are well coated. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Press into bottom of cake pans. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/gravy.yaml b/culinary/recipes/gravy.yaml new file mode 100644 index 0000000..a4164e5 --- /dev/null +++ b/culinary/recipes/gravy.yaml @@ -0,0 +1,92 @@ +schema_version: 2 +id: gravy +revision: 1 +status: draft +title: Gravy +categories: +- sauce +tags: [] +yield: + amount: + quantity: 120.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_03_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 6.7 + unit_id: gram + percentage: 6.7 + - id: line_04_beef_base + reference: + ingredient_id: beef_base + amount: + quantity: 3.2 + unit_id: gram + percentage: 3.2 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 +steps: +- id: step_01 + order: 1 + instruction: Blend base and flour. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Gradually add small amount cold water until smooth. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add boiling water, stirring until smooth. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Bring to low boil. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add oil to pan. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add flour to pan. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/guacamole.yaml b/culinary/recipes/guacamole.yaml new file mode 100644 index 0000000..057421f --- /dev/null +++ b/culinary/recipes/guacamole.yaml @@ -0,0 +1,94 @@ +schema_version: 2 +id: guacamole +revision: 1 +status: draft +title: Guacamole +categories: +- side +tags: +- dip +yield: + amount: + quantity: 103.81 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_avocado + reference: + ingredient_id: avocado + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 2.15 + unit_id: gram + percentage: 2.15 + - id: line_03_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_04_ascorbic_acid + reference: + ingredient_id: ascorbic_acid + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_05_chili_powder + reference: + ingredient_id: chili_powder + amount: + quantity: 0.13 + unit_id: gram + percentage: 0.13 + - id: line_06_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.11 + unit_id: gram + percentage: 0.11 + - id: line_07_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.11 + unit_id: gram + percentage: 0.11 + - id: line_08_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.11 + unit_id: gram + percentage: 0.11 +steps: +- id: step_01 + order: 1 + instruction: Combine all. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mash to desired texture. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/gyro_meat.yaml b/culinary/recipes/gyro_meat.yaml new file mode 100644 index 0000000..19d3071 --- /dev/null +++ b/culinary/recipes/gyro_meat.yaml @@ -0,0 +1,184 @@ +schema_version: 2 +id: gyro_meat +revision: 1 +status: draft +title: Gyro Meat +categories: +- meat +tags: +- beef +yield: + amount: + quantity: 155.45 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_ground_beef_73_27_raw + reference: + ingredient_id: ground_beef_73_27_raw + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water_ice + reference: + ingredient_id: water_ice + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_03_bread_crumbs + reference: + ingredient_id: bread_crumbs + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 7.7 + unit_id: gram + percentage: 7.7 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_08_msg + reference: + ingredient_id: msg + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_09_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_10_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_11_coriander + reference: + ingredient_id: coriander + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_12_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 + - id: line_13_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 + - id: line_14_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +equipment_ids: +- food_processor +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Chill meat to 32 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Hand mix salt, meat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Chill for 1 hr. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine all but ice. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Food processor emulsify until temp climbs to 45 °F. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add ice. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Repeat until well emulsified. + component_ids: + - main +- id: step_08 + order: 8 + instruction: 'Optionally:' + component_ids: + - main +- id: step_09 + order: 9 + instruction: Line sheet pan aluminum foil. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Form meat into loaf 2 in thick. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Bake ≈30 min at 300 °F until 155 °F internal. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/halal_guys_white_sauce_v1.yaml b/culinary/recipes/halal_guys_white_sauce_v1.yaml new file mode 100644 index 0000000..b4556ee --- /dev/null +++ b/culinary/recipes/halal_guys_white_sauce_v1.yaml @@ -0,0 +1,69 @@ +schema_version: 2 +id: halal_guys_white_sauce_v1 +revision: 1 +status: draft +title: Halal Guys White Sauce V1 +categories: +- sauce +tags: +- copycat +- halal-guys +yield: + amount: + quantity: 118.07 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 6.67 + unit_id: gram + percentage: 6.67 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_04_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_05_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 1.4 + unit_id: gram + percentage: 1.4 +steps: +- id: step_01 + order: 1 + instruction: Mix. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/halal_guys_white_sauce_v2.yaml b/culinary/recipes/halal_guys_white_sauce_v2.yaml new file mode 100644 index 0000000..261dc68 --- /dev/null +++ b/culinary/recipes/halal_guys_white_sauce_v2.yaml @@ -0,0 +1,76 @@ +schema_version: 2 +id: halal_guys_white_sauce_v2 +revision: 1 +status: draft +title: Halal Guys White Sauce V2 +categories: +- sauce +tags: +- copycat +- halal-guys +yield: + amount: + quantity: 139.47 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_03_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 14 + unit_id: gram + percentage: 14 + - id: line_04_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_05_cardamom + reference: + ingredient_id: cardamom + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 + - id: line_06_xanthan_gum + reference: + ingredient_id: xanthan_gum + amount: + quantity: 0.12 + unit_id: gram + percentage: 0.12 +steps: +- id: step_01 + order: 1 + instruction: Mix. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/hamburger_bun.yaml b/culinary/recipes/hamburger_bun.yaml new file mode 100644 index 0000000..a9b3185 --- /dev/null +++ b/culinary/recipes/hamburger_bun.yaml @@ -0,0 +1,118 @@ +schema_version: 2 +id: hamburger_bun +revision: 1 +status: draft +title: Hamburger Bun +categories: +- bread +tags: +- bun +- burger +yield: + amount: + quantity: 182.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 63 + unit_id: gram + percentage: 63 + - id: line_03_butter_flavored_shortening + reference: + ingredient_id: butter_flavored_shortening + amount: + quantity: 7.6 + unit_id: gram + percentage: 7.6 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3.8 + unit_id: gram + percentage: 3.8 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 3.8 + unit_id: gram + percentage: 3.8 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: Mix dough to full gluten development. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Divide into 85 g portions. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Shape into smooth balls. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Arrange 6 equidistant dough balls in one parchment-lined 9 in x 13 in pan. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Press dough flat to form oblate spheroid. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Proof in high humidity. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Apply wash and seeds. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Bake 18 min at 380 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/hoagie.yaml b/culinary/recipes/hoagie.yaml new file mode 100644 index 0000000..946b300 --- /dev/null +++ b/culinary/recipes/hoagie.yaml @@ -0,0 +1,75 @@ +schema_version: 2 +id: hoagie +revision: 1 +status: draft +title: Hoagie +categories: +- bread +tags: +- roll +yield: + amount: + quantity: 169 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 57 + unit_id: gram + percentage: 57 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/hot_fudge_v1.yaml b/culinary/recipes/hot_fudge_v1.yaml new file mode 100644 index 0000000..74ccced --- /dev/null +++ b/culinary/recipes/hot_fudge_v1.yaml @@ -0,0 +1,91 @@ +schema_version: 2 +id: hot_fudge_v1 +revision: 1 +status: draft +title: Hot Fudge V1 +categories: +- sauce +tags: +- dessert-sauce +- chocolate +yield: + amount: + quantity: 489 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sugar + reference: + ingredient_id: sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_semisweet_chocolate + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 151 + unit_id: gram + percentage: 151 + - id: line_03_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 116 + unit_id: gram + percentage: 116 + - id: line_04_corn_syrup_light + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 105 + unit_id: gram + percentage: 105 + - id: line_05_shortening + reference: + ingredient_id: shortening + amount: + quantity: 16 + unit_id: gram + percentage: 16 + - id: line_06_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Combine all except vanilla, chocolate. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Boil, remove from heat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add chocolate, vanilla. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Stir. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/hot_fudge_v2.yaml b/culinary/recipes/hot_fudge_v2.yaml new file mode 100644 index 0000000..0668d09 --- /dev/null +++ b/culinary/recipes/hot_fudge_v2.yaml @@ -0,0 +1,120 @@ +schema_version: 2 +id: hot_fudge_v2 +revision: 1 +status: draft +title: Hot Fudge V2 +categories: +- sauce +tags: +- dessert-sauce +- chocolate +yield: + amount: + quantity: 99.75 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 29.7 + unit_id: gram + percentage: 29.7 + basis_member: true + - id: line_02_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 22 + unit_id: gram + percentage: 22 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_dark_cocoa_powder + reference: + ingredient_id: dark_cocoa_powder + amount: + quantity: 12.75 + unit_id: gram + percentage: 12.75 + - id: line_05_light_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_06_bittersweet_chocolate + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 6 + unit_id: gram + percentage: 6 + notes: bittersweet chocolate + - id: line_07_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 3.4 + unit_id: gram + percentage: 3.4 + - id: line_08_lecithin_liquid_soy + reference: + ingredient_id: lecithin_liquid_soy + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 + - id: line_09_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_10_salt + reference: + ingredient_id: salt + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 +steps: +- id: step_01 + order: 1 + instruction: Combine all except vanilla, chocolate, cocoa. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Boil, remove from heat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add chocolate, vanilla. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Stir. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/imos_pizza_dough.yaml b/culinary/recipes/imos_pizza_dough.yaml new file mode 100644 index 0000000..80c3ad1 --- /dev/null +++ b/culinary/recipes/imos_pizza_dough.yaml @@ -0,0 +1,108 @@ +schema_version: 2 +id: imos_pizza_dough +revision: 1 +status: draft +title: Imo's Pizza Dough +categories: +- bread +tags: +- dough +- pizza +- copycat +- imos +yield: + amount: + quantity: 160.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +steps: +- id: step_01 + order: 1 + instruction: Mix to high gluten development. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Shape balls, cold ferment 24-72 hr. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Roll 16 in. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Preheat steel 500 °F. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Lower to 450 °F. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Bake 11 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Transfer to cooling rack 6 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml b/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml new file mode 100644 index 0000000..bb5c666 --- /dev/null +++ b/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml @@ -0,0 +1,97 @@ +schema_version: 2 +id: jimmy_johns_kickin_ranch_sauce +revision: 1 +status: draft +title: Jimmy John's Kickin' Ranch Sauce +categories: +- sauce +tags: +- dressing +- ranch +- copycat +- jimmy-johns +yield: + amount: + quantity: 177.14 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_buttermilk + reference: + ingredient_id: buttermilk + amount: + quantity: 54.2 + unit_id: gram + percentage: 54.2 + - id: line_03_hot_cherry_peppers + reference: + ingredient_id: hot_cherry_peppers + amount: + quantity: 11.59 + unit_id: gram + percentage: 11.59 + - id: line_04_hot_pepper_juice + reference: + ingredient_id: hot_pepper_juice + amount: + quantity: 5.8 + unit_id: gram + percentage: 5.8 + - id: line_05_ranch_seasoning + reference: + ingredient_id: hidden_valley_ranch_dry_seasoning + amount: + quantity: 5.2 + unit_id: gram + percentage: 5.2 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_07_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.05 + unit_id: gram + percentage: 0.05 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Blend peppers, juice, 1/2 buttermilk. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add ranch packet, garlic salt. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whisk with mayo, remaining buttermilk mix. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/korean_coater_mix.yaml b/culinary/recipes/korean_coater_mix.yaml new file mode 100644 index 0000000..b9dc94a --- /dev/null +++ b/culinary/recipes/korean_coater_mix.yaml @@ -0,0 +1,73 @@ +schema_version: 2 +id: korean_coater_mix +revision: 1 +status: draft +title: Korean Coater Mix +categories: +- component +tags: +- coater +- fried +- korean +yield: + amount: + quantity: 129 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_salt + reference: + ingredient_id: salt + amount: + quantity: 27 + unit_id: gram + percentage: 27 + - id: line_03_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Combine ingredients in a bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add chicken and toss until thoroughly coated. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Shake vigorously to remove excess coating. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Rest uncovered in the refrigerator for 30 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/korean_fry_batter.yaml b/culinary/recipes/korean_fry_batter.yaml new file mode 100644 index 0000000..85f93a6 --- /dev/null +++ b/culinary/recipes/korean_fry_batter.yaml @@ -0,0 +1,89 @@ +schema_version: 2 +id: korean_fry_batter +revision: 1 +status: draft +title: Korean Fry Batter +categories: +- component +tags: +- batter +- fried +- korean +yield: + amount: + quantity: 524 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 164 + unit_id: gram + percentage: 164 + - id: line_03_vodka + reference: + ingredient_id: vodka + amount: + quantity: 164 + unit_id: gram + percentage: 164 + - id: line_04_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 82 + unit_id: gram + percentage: 82 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_06_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Whisk together dry ingredients. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk together wet ingredients. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whisk all ingredients together until smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/lemon_curd.yaml b/culinary/recipes/lemon_curd.yaml new file mode 100644 index 0000000..985a510 --- /dev/null +++ b/culinary/recipes/lemon_curd.yaml @@ -0,0 +1,93 @@ +schema_version: 2 +id: lemon_curd +revision: 1 +status: draft +title: Lemon Curd +categories: +- sauce +tags: +- dessert-sauce +- filling +yield: + amount: + quantity: 242.22 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sugar + reference: + ingredient_id: sugar + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_egg_yolk + reference: + ingredient_id: egg_yolk + amount: + quantity: 48.89 + unit_id: gram + percentage: 48.89 + - id: line_04_butter + reference: + ingredient_id: butter + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_05_lemon_zest + reference: + ingredient_id: lemon_zest + amount: + quantity: 3.33 + unit_id: gram + percentage: 3.33 +equipment_ids: +- blender +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Combine sugar, egg yolks, lemon juice, and lemon zest in a stainless steel bowl over a + double boiler. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Stir occasionally until the mixture thickens to a ketchup-like consistency. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Remove from heat and strain into a clean container. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add butter at 90°F (32°C) to 95°F (35°C) and blend with an immersion blender. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Cover to the surface and refrigerate. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/lo_mein_sauce.yaml b/culinary/recipes/lo_mein_sauce.yaml new file mode 100644 index 0000000..5afbb55 --- /dev/null +++ b/culinary/recipes/lo_mein_sauce.yaml @@ -0,0 +1,101 @@ +schema_version: 2 +id: lo_mein_sauce +revision: 1 +status: draft +title: Lo Mein Sauce +categories: +- sauce +tags: +- chinese +yield: + amount: + quantity: 271 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_03_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 16 + unit_id: gram + percentage: 16 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 13 + unit_id: gram + percentage: 13 + - id: line_06_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_07_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_08_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_09_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Bring to boil, stirring vigorously until thickened. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mac_cheese_sauce.yaml b/culinary/recipes/mac_cheese_sauce.yaml new file mode 100644 index 0000000..1d8ca10 --- /dev/null +++ b/culinary/recipes/mac_cheese_sauce.yaml @@ -0,0 +1,66 @@ +schema_version: 2 +id: mac_cheese_sauce +revision: 1 +status: draft +title: Mac & Cheese Sauce +categories: +- sauce +tags: +- cheese +yield: + amount: + quantity: 196 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cheddar_cheese + reference: + ingredient_id: cheddar_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 93 + unit_id: gram + percentage: 93 + - id: line_03_sodium_citrate + reference: + ingredient_id: sodium_citrate + amount: + quantity: 3 + unit_id: gram + percentage: 3 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Dissolve sodium citrate, water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Bring to simmer. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add shredded cheese slowly, whisk constantly. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mashed_potato.yaml b/culinary/recipes/mashed_potato.yaml new file mode 100644 index 0000000..3e58b6b --- /dev/null +++ b/culinary/recipes/mashed_potato.yaml @@ -0,0 +1,81 @@ +schema_version: 2 +id: mashed_potato +revision: 1 +status: draft +title: Mashed Potato +categories: +- side +tags: +- potato +yield: + amount: + quantity: 131 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_potato_russet + reference: + ingredient_id: potato_russet + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_liquid + reference: + ingredient_id: milk + amount: + quantity: 22 + unit_id: gram + percentage: 22 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Peel potato. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Cut potato into cubes. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Simmer until soft. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine all. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mash. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/meatball.yaml b/culinary/recipes/meatball.yaml new file mode 100644 index 0000000..c1c16e8 --- /dev/null +++ b/culinary/recipes/meatball.yaml @@ -0,0 +1,156 @@ +schema_version: 2 +id: meatball +revision: 1 +status: draft +title: Meatball +categories: +- meat +tags: +- beef +yield: + amount: + quantity: 159.58 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_meat_73_27 + reference: + ingredient_id: ground_beef_73_27_raw + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 22 + unit_id: gram + percentage: 22 + - id: line_03_bread_crumbs + reference: + ingredient_id: bread_crumbs + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_05_buttermilk_powder + reference: + ingredient_id: buttermilk_powder + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_gelatin + reference: + ingredient_id: gelatin + amount: + quantity: 0.78 + unit_id: gram + percentage: 0.78 + - id: line_09_onion_dehydrated_flake + reference: + ingredient_id: onion_dehydrated_flake + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_10_fennel_seed + reference: + ingredient_id: fennel_seed + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_11_msg + reference: + ingredient_id: msg + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_12_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_13_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_14_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 +steps: +- id: step_01 + order: 1 + instruction: Dissolve gelatin in hot water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine everything except egg, meat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Paddle mix. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix until light. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Add meat. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Mix, scrape til combined. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mexicali_dip.yaml b/culinary/recipes/mexicali_dip.yaml new file mode 100644 index 0000000..bb64aac --- /dev/null +++ b/culinary/recipes/mexicali_dip.yaml @@ -0,0 +1,97 @@ +schema_version: 2 +id: mexicali_dip +revision: 1 +status: draft +title: Mexicali Dip +categories: +- sauce +tags: +- dip +- mexican +yield: + amount: + quantity: 254.9 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sour_cream + reference: + ingredient_id: sour_cream + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_04_monterey_jack_cheese + reference: + ingredient_id: monterey_jack_cheese + amount: + quantity: 28 + unit_id: gram + percentage: 28 + - id: line_05_jalapeno_peppers_pickled + reference: + ingredient_id: jalapeno_peppers_pickled + amount: + quantity: 13 + unit_id: gram + percentage: 13 + - id: line_06_chipotle_pepper_sauce_tobasco + reference: + ingredient_id: chipotle_pepper_sauce_tobasco + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_08_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_09_onion_dehydrated_powder + reference: + ingredient_id: onion_dehydrated_powder + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mexican_rice.yaml b/culinary/recipes/mexican_rice.yaml new file mode 100644 index 0000000..a434ddb --- /dev/null +++ b/culinary/recipes/mexican_rice.yaml @@ -0,0 +1,95 @@ +schema_version: 2 +id: mexican_rice +revision: 1 +status: draft +title: Mexican Rice +categories: +- side +tags: +- rice +- mexican +yield: + amount: + quantity: 257 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_rice + reference: + ingredient_id: rice + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 140 + unit_id: gram + percentage: 140 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_04_tomato_bouillon + reference: + ingredient_id: tomato_bouillon + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_05_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_07_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 1.3 + unit_id: gram + percentage: 1.3 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 0.9 + unit_id: gram + percentage: 0.9 +steps: +- id: step_01 + order: 1 + instruction: Add rice, water, oil to rice cooker; cook + component_ids: + - main +- id: step_02 + order: 2 + instruction: season with remaining ingredients + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mexican_white_sauce.yaml b/culinary/recipes/mexican_white_sauce.yaml new file mode 100644 index 0000000..1f62aca --- /dev/null +++ b/culinary/recipes/mexican_white_sauce.yaml @@ -0,0 +1,138 @@ +schema_version: 2 +id: mexican_white_sauce +revision: 1 +status: draft +title: Mexican White Sauce +categories: +- sauce +tags: +- mexican +yield: + amount: + quantity: 693.45 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 425 + unit_id: gram + percentage: 425 + - id: line_03_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 44 + unit_id: gram + percentage: 44 + - id: line_05_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 34 + unit_id: gram + percentage: 34 + - id: line_06_jalapeno_diced + reference: + ingredient_id: jalapeno_peppers_pickled + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_hot_sauce + reference: + ingredient_id: hot_sauce + amount: + quantity: 9 + unit_id: gram + percentage: 9 + - id: line_08_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 5.75 + unit_id: gram + percentage: 5.75 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Dissolve chicken base in water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Melt oil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add flour to oil. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Heat until flour cooks. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Whisk in chicken stock, heat until smooth. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add hot mixture to cream cheese. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Melt and whisk smooth. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Add back to pot. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Mix in remaining ingredients. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/milk.yaml b/culinary/recipes/milk.yaml new file mode 100644 index 0000000..70f056e --- /dev/null +++ b/culinary/recipes/milk.yaml @@ -0,0 +1,47 @@ +schema_version: 2 +id: milk +revision: 1 +status: draft +title: Milk +categories: +- component +tags: +- base-formula +yield: + amount: + quantity: 111.11 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 11.11 + unit_id: gram + percentage: 11.11 +steps: +- id: step_01 + order: 1 + instruction: Dissolve powder in water. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mod_pizza_dough.yaml b/culinary/recipes/mod_pizza_dough.yaml new file mode 100644 index 0000000..815b0c5 --- /dev/null +++ b/culinary/recipes/mod_pizza_dough.yaml @@ -0,0 +1,98 @@ +schema_version: 2 +id: mod_pizza_dough +revision: 1 +status: draft +title: MOD Pizza Dough +categories: +- bread +tags: +- dough +- pizza +- copycat +- mod +yield: + amount: + quantity: 159.25 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2.75 + unit_id: gram + percentage: 2.75 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +steps: +- id: step_01 + order: 1 + instruction: Combine and mix dough medium development. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Divide. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Shape dough into ball. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Lightly oil ball. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Store in air-tight container and refrigerate. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml b/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml new file mode 100644 index 0000000..4bd558d --- /dev/null +++ b/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml @@ -0,0 +1,73 @@ +schema_version: 2 +id: mozzarella_cheese_melt_stuffed +revision: 1 +status: draft +title: Mozzarella Cheese Melt Stuffed +categories: +- component +tags: +- cheese +yield: + amount: + quantity: 135.66 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mozzarella_cheese + reference: + ingredient_id: mozzarella_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_03_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 3.33 + unit_id: gram + percentage: 3.33 + - id: line_04_sodium_citrate + reference: + ingredient_id: sodium_citrate + amount: + quantity: 2.33 + unit_id: gram + percentage: 2.33 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Heat water, milk powder 150 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk in cheese, sodium citrate. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Stir until combined. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/oat_chocolate_cookie.yaml b/culinary/recipes/oat_chocolate_cookie.yaml new file mode 100644 index 0000000..e9ec911 --- /dev/null +++ b/culinary/recipes/oat_chocolate_cookie.yaml @@ -0,0 +1,137 @@ +schema_version: 2 +id: oat_chocolate_cookie +revision: 1 +status: draft +title: Oat Chocolate Cookie +categories: +- dessert +tags: +- cookie +- chocolate +yield: + amount: + quantity: 366.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_oats + reference: + ingredient_id: oats + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 118 + unit_id: gram + percentage: 118 + - id: line_03_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 66 + unit_id: gram + percentage: 66 + - id: line_04_milk + reference: + ingredient_id: milk + amount: + quantity: 45 + unit_id: gram + percentage: 45 + - id: line_05_butter + reference: + ingredient_id: butter + amount: + quantity: 22 + unit_id: gram + percentage: 22 + - id: line_06_cocoa_powder + reference: + ingredient_id: cocoa_powder + amount: + quantity: 8.5 + unit_id: gram + percentage: 8.5 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- saucepan +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine the butter, sugar, milk, and cocoa powder together in a medium saucepan over medium + heat. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk constantly until the butter melts. whisking occasionally, bring to a boil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Once boiling, stop whisking and allow to boil for 1 min. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Remove from heat, then immediately stir in the peanut butter and vanilla extract until + completely combined. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Stir in the oats and salt. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Allow mixture to sit for 5 min. This allows the oats to soak up some moisture. + component_ids: + - main +- id: step_07 + order: 7 + instruction: During the 5 min, line two baking sheets with parchment paper or silicone baking mats. + and make sure there is enough room in your refrigerator for the baking sheets. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Using a 1 tbsp cookie scoop, drop a tablespoon of dough onto the lined baking sheets. if + desired, slightly flatten down with the back of a spoon. repeat with the rest of the dough. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Refrigerate the cookies for 30-60 min to set. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/oatmeal_raisin_cookie.yaml b/culinary/recipes/oatmeal_raisin_cookie.yaml new file mode 100644 index 0000000..379d7e9 --- /dev/null +++ b/culinary/recipes/oatmeal_raisin_cookie.yaml @@ -0,0 +1,103 @@ +schema_version: 2 +id: oatmeal_raisin_cookie +revision: 1 +status: draft +title: Oatmeal Raisin Cookie +categories: +- dessert +tags: +- cookie +yield: + amount: + quantity: 513.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 145 + unit_id: gram + percentage: 145 + - id: line_03_oats + reference: + ingredient_id: oats + amount: + quantity: 85 + unit_id: gram + percentage: 85 + - id: line_04_raisins + reference: + ingredient_id: raisins + amount: + quantity: 72.5 + unit_id: gram + percentage: 72.5 + - id: line_05_butter + reference: + ingredient_id: butter + amount: + quantity: 68.75 + unit_id: gram + percentage: 68.75 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 32.5 + unit_id: gram + percentage: 32.5 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_09_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + - id: line_10_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/orange_chicken_sauce.yaml b/culinary/recipes/orange_chicken_sauce.yaml new file mode 100644 index 0000000..2362146 --- /dev/null +++ b/culinary/recipes/orange_chicken_sauce.yaml @@ -0,0 +1,186 @@ +schema_version: 2 +id: orange_chicken_sauce +revision: 1 +status: draft +title: Orange Chicken Sauce +categories: +- sauce +tags: +- chinese +yield: + amount: + quantity: 459.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_orange_juice + reference: + ingredient_id: orange_juice + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_03_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_06_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_07_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 32 + unit_id: gram + percentage: 32 + - id: line_08_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 13.3 + unit_id: gram + percentage: 13.3 + - id: line_09_orange_extract + reference: + ingredient_id: orange_extract + amount: + quantity: 8.3 + unit_id: gram + percentage: 8.3 + - id: line_10_sambal_oelek + reference: + ingredient_id: sambal_oelek + amount: + quantity: 8.3 + unit_id: gram + percentage: 8.3 + - id: line_11_garlic_minced + reference: + ingredient_id: garlic + amount: + quantity: 4.2 + unit_id: gram + percentage: 4.2 + prep: + - action_id: mince + - id: line_12_ginger_grated + reference: + ingredient_id: ginger + amount: + quantity: 4.2 + unit_id: gram + percentage: 4.2 + prep: + - action_id: grate + - id: line_13_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 4.2 + unit_id: gram + percentage: 4.2 + - id: line_14_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_15_msg + reference: + ingredient_id: msg + amount: + quantity: 1.6 + unit_id: gram + percentage: 1.6 + - id: line_16_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk until combined, dissolved. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Heat oil. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add garlic, ginger, sambal. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Cook < 60 sec. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Cooking wine to deglaze. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add sauce mixture to this pan. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Stir in cornstarch slurry. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/orange_juice.yaml b/culinary/recipes/orange_juice.yaml new file mode 100644 index 0000000..5c348d1 --- /dev/null +++ b/culinary/recipes/orange_juice.yaml @@ -0,0 +1,46 @@ +schema_version: 2 +id: orange_juice +revision: 1 +status: draft +title: Orange Juice +categories: +- beverage +tags: [] +yield: + amount: + quantity: 139 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_orange_juice_concentrate + reference: + ingredient_id: orange_juice_concentrate + amount: + quantity: 39 + unit_id: gram + percentage: 39 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_dark_sauce.yaml b/culinary/recipes/p_f_changs_dark_sauce.yaml new file mode 100644 index 0000000..ddec076 --- /dev/null +++ b/culinary/recipes/p_f_changs_dark_sauce.yaml @@ -0,0 +1,96 @@ +schema_version: 2 +id: p_f_changs_dark_sauce +revision: 1 +status: draft +title: P. F. Chang's Dark Sauce +categories: +- sauce +tags: +- chinese +- copycat +- pf-changs +yield: + amount: + quantity: 447.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_soy_sauce_light_low_sodium + reference: + ingredient_id: soy_sauce_light_low_sodium + amount: + quantity: 150 + unit_id: gram + percentage: 150 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 85 + unit_id: gram + percentage: 85 + - id: line_04_michiu_wine + reference: + ingredient_id: michiu_wine + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_05_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 33 + unit_id: gram + percentage: 33 + - id: line_06_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 4.5 + unit_id: gram + percentage: 4.5 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Dissolve sugar, chicken base in water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Heat if necessary. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whisk in dry. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_honey_sauce.yaml b/culinary/recipes/p_f_changs_honey_sauce.yaml new file mode 100644 index 0000000..ce370b0 --- /dev/null +++ b/culinary/recipes/p_f_changs_honey_sauce.yaml @@ -0,0 +1,137 @@ +schema_version: 2 +id: p_f_changs_honey_sauce +revision: 1 +status: draft +title: P. F. Chang's Honey Sauce +categories: +- sauce +tags: +- chinese +- copycat +- pf-changs +yield: + amount: + quantity: 334.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 80.8 + unit_id: gram + percentage: 80.8 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 73.8 + unit_id: gram + percentage: 73.8 + - id: line_04_water + reference: + ingredient_id: water + amount: + quantity: 28.3 + unit_id: gram + percentage: 28.3 + - id: line_05_soy_sauce_light + reference: + ingredient_id: soy_sauce_light + amount: + quantity: 19.2 + unit_id: gram + percentage: 19.2 + - id: line_06_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_07_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 11 + unit_id: gram + percentage: 11 + - id: line_08_garlic_minced + reference: + ingredient_id: garlic + amount: + quantity: 3.8 + unit_id: gram + percentage: 3.8 + prep: + - action_id: mince + - id: line_09_dried_chilis + reference: + ingredient_id: dried_chilis + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Heat oil in pot, medium heat. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add chilis, saute until dark. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add garlic. saute briefly, < 60 sec. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add remaining except vinegar. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Whisk to dissolve and combine. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Turn off heat, leave for ≈10 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add vinegar, whisk to incorporated. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Strain out garlic and chilis. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_kung_pao_sauce.yaml b/culinary/recipes/p_f_changs_kung_pao_sauce.yaml new file mode 100644 index 0000000..c4ac6ba --- /dev/null +++ b/culinary/recipes/p_f_changs_kung_pao_sauce.yaml @@ -0,0 +1,91 @@ +schema_version: 2 +id: p_f_changs_kung_pao_sauce +revision: 1 +status: draft +title: P. F. Chang's Kung Pao Sauce +categories: +- sauce +tags: +- chinese +- copycat +- pf-changs +yield: + amount: + quantity: 777.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_soy_sauce_light_low_sodium + reference: + ingredient_id: soy_sauce_light_low_sodium + amount: + quantity: 325 + unit_id: gram + percentage: 325 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 130 + unit_id: gram + percentage: 130 + - id: line_04_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_05_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_06_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 58 + unit_id: gram + percentage: 58 + - id: line_07_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 11 + unit_id: gram + percentage: 11 + - id: line_08_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 +steps: +- id: step_01 + order: 1 + instruction: Mix everything. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml b/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml new file mode 100644 index 0000000..017823b --- /dev/null +++ b/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml @@ -0,0 +1,102 @@ +schema_version: 2 +id: p_f_changs_mongolian_beef_sauce +revision: 1 +status: draft +title: P. F. Chang's Mongolian Beef Sauce +categories: +- sauce +tags: +- chinese +- beef +- copycat +- pf-changs +yield: + amount: + quantity: 534 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 165 + unit_id: gram + percentage: 165 + - id: line_03_soy_sauce_light_low_sodium + reference: + ingredient_id: soy_sauce_light_low_sodium + amount: + quantity: 150 + unit_id: gram + percentage: 150 + - id: line_04_shaoxing_wine + reference: + ingredient_id: shaoxing_wine + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_05_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 33 + unit_id: gram + percentage: 33 + - id: line_06_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_08_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 5 + unit_id: gram + percentage: 5 +steps: +- id: step_01 + order: 1 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Bring to boil, stirring vigorously. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Until thickened slightly. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml b/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml new file mode 100644 index 0000000..df4d9e5 --- /dev/null +++ b/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml @@ -0,0 +1,104 @@ +schema_version: 2 +id: p_f_changs_spicy_chicken_sauce +revision: 1 +status: draft +title: P. F. Chang's Spicy Chicken Sauce +categories: +- sauce +tags: +- chinese +- chicken +- copycat +- pf-changs +yield: + amount: + quantity: 207.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 45 + unit_id: gram + percentage: 45 + - id: line_03_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 37 + unit_id: gram + percentage: 37 + - id: line_04_chili_crisp + reference: + ingredient_id: chili_crisp + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_05_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_06_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 5.5 + unit_id: gram + percentage: 5.5 + - id: line_07_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_08_sesame_oil + reference: + ingredient_id: sesame_oil + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_09_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Bring to boil, stirring vigorously until thickened. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/p_f_changs_umami_sauce.yaml b/culinary/recipes/p_f_changs_umami_sauce.yaml new file mode 100644 index 0000000..761d882 --- /dev/null +++ b/culinary/recipes/p_f_changs_umami_sauce.yaml @@ -0,0 +1,78 @@ +schema_version: 2 +id: p_f_changs_umami_sauce +revision: 1 +status: draft +title: P. F. Chang's Umami Sauce +categories: +- sauce +tags: +- chinese +- copycat +- pf-changs +yield: + amount: + quantity: 327.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_oyster_sauce + reference: + ingredient_id: oyster_sauce + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_michiu_wine + reference: + ingredient_id: michiu_wine + amount: + quantity: 79 + unit_id: gram + percentage: 79 + - id: line_03_soy_sauce_dark + reference: + ingredient_id: soy_sauce_dark + amount: + quantity: 79 + unit_id: gram + percentage: 79 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 66 + unit_id: gram + percentage: 66 + - id: line_05_white_pepper + reference: + ingredient_id: white_pepper + amount: + quantity: 3.2 + unit_id: gram + percentage: 3.2 +equipment_ids: +- mixing_bowl +- whisk +steps: +- id: step_01 + order: 1 + instruction: Add all to bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk until dissolved. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pancakes.yaml b/culinary/recipes/pancakes.yaml new file mode 100644 index 0000000..d07a377 --- /dev/null +++ b/culinary/recipes/pancakes.yaml @@ -0,0 +1,111 @@ +schema_version: 2 +id: pancakes +revision: 1 +status: draft +title: Pancakes +categories: +- breakfast +tags: +- batter +yield: + amount: + quantity: 338.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 135 + unit_id: gram + percentage: 135 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 44 + unit_id: gram + percentage: 44 + - id: line_04_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_05_buttermilk_powder + reference: + ingredient_id: buttermilk_powder + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 12.5 + unit_id: gram + percentage: 12.5 + - id: line_07_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- griddle +steps: +- id: step_01 + order: 1 + instruction: Sift together flour, salt, baking powder, and sugar. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine egg, water, milk powder, and oil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the liquid mixture to the dry mixture. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix until just combined. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Cook 2 oz batter portions on a 375 °F griddle. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml b/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml new file mode 100644 index 0000000..00c517f --- /dev/null +++ b/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml @@ -0,0 +1,92 @@ +schema_version: 2 +id: papa_johns_garlic_dipping_sauce +revision: 1 +status: draft +title: Papa Johns Garlic Dipping Sauce +categories: +- sauce +tags: +- dip +- copycat +- papa-johns +yield: + amount: + quantity: 173.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_butter_flavored_shortening + reference: + ingredient_id: butter_flavored_shortening + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 69 + unit_id: gram + percentage: 69 + - id: line_03_salt + reference: + ingredient_id: salt + amount: + quantity: 2.1 + unit_id: gram + percentage: 2.1 + - id: line_04_garlic_dehydrated + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_05_lecithin_liquid_soy + reference: + ingredient_id: lecithin_liquid_soy + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Heat oil to liquid state. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Disperse lecithin in oil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add all to blender. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Blend til emulsified. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Allow to cool. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/papa_johns_pizza.yaml b/culinary/recipes/papa_johns_pizza.yaml new file mode 100644 index 0000000..c9ffe56 --- /dev/null +++ b/culinary/recipes/papa_johns_pizza.yaml @@ -0,0 +1,102 @@ +schema_version: 2 +id: papa_johns_pizza +revision: 1 +status: draft +title: Papa Johns Pizza +categories: +- bread +tags: +- pizza +- copycat +- papa-johns +yield: + amount: + quantity: 169.62 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 56 + unit_id: gram + percentage: 56 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 5.89 + unit_id: gram + percentage: 5.89 + - id: line_04_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 5.55 + unit_id: gram + percentage: 5.55 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1.9 + unit_id: gram + percentage: 1.9 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 0.28 + unit_id: gram + percentage: 0.28 +steps: +- id: step_01 + order: 1 + instruction: Mix. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Shape into balls. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Cold ferment 24-72 hr. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Hand stretch to size. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Bake 500 °F near bottom rack 8-9 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Transfer to cooling rack 5 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pate_brise.yaml b/culinary/recipes/pate_brise.yaml new file mode 100644 index 0000000..dadd067 --- /dev/null +++ b/culinary/recipes/pate_brise.yaml @@ -0,0 +1,89 @@ +schema_version: 2 +id: pate_brise +revision: 1 +status: draft +title: Pâte Brisée +categories: +- pastry +tags: +- crust +yield: + amount: + quantity: 192.57 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 32.5 + unit_id: gram + percentage: 32.5 + - id: line_04_water + reference: + ingredient_id: water + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.05 + unit_id: gram + percentage: 0.05 + - id: line_08_citric_acid + reference: + ingredient_id: citric_acid + amount: + quantity: 0.02 + unit_id: gram + percentage: 0.02 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/peanut_butter_cookie.yaml b/culinary/recipes/peanut_butter_cookie.yaml new file mode 100644 index 0000000..9f95d8b --- /dev/null +++ b/culinary/recipes/peanut_butter_cookie.yaml @@ -0,0 +1,130 @@ +schema_version: 2 +id: peanut_butter_cookie +revision: 1 +status: draft +title: Peanut Butter Cookie +categories: +- dessert +tags: +- cookie +yield: + amount: + quantity: 368.03 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 68.75 + unit_id: gram + percentage: 68.75 + - id: line_03_butter + reference: + ingredient_id: butter + amount: + quantity: 60.71 + unit_id: gram + percentage: 60.71 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 53.57 + unit_id: gram + percentage: 53.57 + - id: line_05_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 52.68 + unit_id: gram + percentage: 52.68 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 26.79 + unit_id: gram + percentage: 26.79 + - id: line_07_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 3.93 + unit_id: gram + percentage: 3.93 + - id: line_08_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.89 + unit_id: gram + percentage: 0.89 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 0.71 + unit_id: gram + percentage: 0.71 +equipment_ids: +- oven +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Combine the dry ingredients and reserve. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Cream the butter and sugars. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the eggs and vanilla, then the peanut butter. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add the dry ingredients and mix until well incorporated. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Scale into 1000 g pieces and roll into 17 in logs (sheet pan width). + component_ids: + - main +- id: step_06 + order: 6 + instruction: Wrap each log in parchment, and refrigerate until ready to bake. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Cut to the desired size [2 oz (50 g) to 4 oz (100 g)], place on parchment-lined sheet pans, + and bake at 350 °F (177 °C) in a convection oven for 12 to 15 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pesto.yaml b/culinary/recipes/pesto.yaml new file mode 100644 index 0000000..5984202 --- /dev/null +++ b/culinary/recipes/pesto.yaml @@ -0,0 +1,98 @@ +schema_version: 2 +id: pesto +revision: 1 +status: draft +title: Pesto +categories: +- sauce +tags: [] +yield: + amount: + quantity: 183.51 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_basil + reference: + ingredient_id: basil + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_walnut + reference: + ingredient_id: walnut + amount: + quantity: 25.77 + unit_id: gram + percentage: 25.77 + - id: line_03_parmesan_cheese + reference: + ingredient_id: parmesan_cheese + amount: + quantity: 22.68 + unit_id: gram + percentage: 22.68 + - id: line_04_olive_oil + reference: + ingredient_id: olive_oil + amount: + quantity: 21.31 + unit_id: gram + percentage: 21.31 + - id: line_05_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 8.93 + unit_id: gram + percentage: 8.93 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2.41 + unit_id: gram + percentage: 2.41 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2.41 + unit_id: gram + percentage: 2.41 +equipment_ids: +- food_processor +steps: +- id: step_01 + order: 1 + instruction: Pick fresh basil, rinse, and lightly dry. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Shred fresh parmesan. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add walnuts, parmesan, lemon juice, olive oil, salt, sugar, and basil to food processor. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Pulse until pieces are small and mixture is smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/philly_steak.yaml b/culinary/recipes/philly_steak.yaml new file mode 100644 index 0000000..f5eafd1 --- /dev/null +++ b/culinary/recipes/philly_steak.yaml @@ -0,0 +1,142 @@ +schema_version: 2 +id: philly_steak +revision: 1 +status: draft +title: Philly Steak +categories: +- meat +tags: +- beef +yield: + amount: + quantity: 156.92 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_ground_beef_73_27_raw + reference: + ingredient_id: ground_beef_73_27_raw + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water_ice + reference: + ingredient_id: water_ice + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_03_bread_crumbs + reference: + ingredient_id: bread_crumbs + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 7.7 + unit_id: gram + percentage: 7.7 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_dextrose + reference: + ingredient_id: dextrose + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 + - id: line_09_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_10_msg + reference: + ingredient_id: msg + amount: + quantity: 0.27 + unit_id: gram + percentage: 0.27 + - id: line_11_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.15 + unit_id: gram + percentage: 0.15 +equipment_ids: +- food_processor +steps: +- id: step_01 + order: 1 + instruction: Chill meat to 32 °F. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Hand mix salt, meat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Chill for 1 hr. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine all but ice. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Food processor emulsify until temp climbs to 45 °F. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add ice. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Repeat until well emulsified. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pie_quiche_crust.yaml b/culinary/recipes/pie_quiche_crust.yaml new file mode 100644 index 0000000..49d5f1d --- /dev/null +++ b/culinary/recipes/pie_quiche_crust.yaml @@ -0,0 +1,116 @@ +schema_version: 2 +id: pie_quiche_crust +revision: 1 +status: draft +title: Pie/Quiche Crust +categories: +- pastry +tags: +- crust +yield: + amount: + quantity: 215 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 80 + unit_id: gram + percentage: 80 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- food_processor +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: In food processor, combine sugar, salt, 2/3 flour. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Spread very cold fat over top. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Pulse until very large clumping. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add remaining flour. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Pulse until come together. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Transfer to bowl. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add cold water. + component_ids: + - main +- id: step_08 + order: 8 + instruction: With spatula, fold into ball. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Refridgerate 2 hr. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Roll out 1/8 in thick. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pineapple_salsa.yaml b/culinary/recipes/pineapple_salsa.yaml new file mode 100644 index 0000000..ec9565c --- /dev/null +++ b/culinary/recipes/pineapple_salsa.yaml @@ -0,0 +1,96 @@ +schema_version: 2 +id: pineapple_salsa +revision: 1 +status: draft +title: Pineapple Salsa +categories: +- sauce +tags: +- salsa +yield: + amount: + quantity: 173.22 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_crushed_in_juice + reference: + ingredient_id: tomato_crushed_in_juice + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_pineapple_crushed_in_juice + reference: + ingredient_id: pineapple_crushed_in_juice + amount: + quantity: 42 + unit_id: gram + percentage: 42 + - id: line_03_tomato_paste + reference: + ingredient_id: tomato_paste + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_04_jalapeno_pickled_diced + reference: + ingredient_id: jalapeno_peppers_pickled + amount: + quantity: 6.67 + unit_id: gram + percentage: 6.67 + - id: line_05_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 6.5 + unit_id: gram + percentage: 6.5 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 4.2 + unit_id: gram + percentage: 4.2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_08_onion_flake + reference: + ingredient_id: onion_dehydrated_flake + amount: + quantity: 0.55 + unit_id: gram + percentage: 0.55 + - id: line_09_chipotle_powder + reference: + ingredient_id: chipotle_powder + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 +steps: +- id: step_01 + order: 1 + instruction: Combine all. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pistachio_shortbread_cookie.yaml b/culinary/recipes/pistachio_shortbread_cookie.yaml new file mode 100644 index 0000000..49e9ce9 --- /dev/null +++ b/culinary/recipes/pistachio_shortbread_cookie.yaml @@ -0,0 +1,132 @@ +schema_version: 2 +id: pistachio_shortbread_cookie +revision: 1 +status: draft +title: Pistachio Shortbread Cookie +categories: +- dessert +tags: +- cookie +yield: + amount: + quantity: 265.86 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_butter + reference: + ingredient_id: butter + amount: + quantity: 79 + unit_id: gram + percentage: 79 + - id: line_03_pistachio_nuts + reference: + ingredient_id: pistachio_nuts + amount: + quantity: 46 + unit_id: gram + percentage: 46 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 37 + unit_id: gram + percentage: 37 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2.1 + unit_id: gram + percentage: 2.1 + - id: line_06_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.88 + unit_id: gram + percentage: 0.88 + - id: line_07_almond_extract + reference: + ingredient_id: almond_extract + amount: + quantity: 0.88 + unit_id: gram + percentage: 0.88 +equipment_ids: +- food_processor +- oven +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Pulse flour, sugar, salt, pistachios, and extracts in food processor until pistachios are + finely ground. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Scatter cold butter chunks in food processor. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Pulse mixture until ingredients form into dough and stick together. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Form dough into log on plastic wrap (2 in by 10 in). + component_ids: + - main +- id: step_05 + order: 5 + instruction: Refrigerate for 2 hr. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Preheat oven to 325 °F and line baking sheet with parchment. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Cut dough log into 1/2 in cookies. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Brush top of each cookie with water and sprinkle with turbinado. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Bake for 15-18 min until golden brown. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Let cookies cool on baking sheet for 5 min, then transfer to wire rack to cool completely. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pita.yaml b/culinary/recipes/pita.yaml new file mode 100644 index 0000000..607e758 --- /dev/null +++ b/culinary/recipes/pita.yaml @@ -0,0 +1,114 @@ +schema_version: 2 +id: pita +revision: 1 +status: draft +title: Pita +categories: +- bread +tags: [] +yield: + amount: + quantity: 183.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 61 + unit_id: gram + percentage: 61 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 13.4 + unit_id: gram + percentage: 13.4 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 4.5 + unit_id: gram + percentage: 4.5 + - id: line_05_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: Mix all but oil until combined. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add oil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix total < 10 min. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Divide into 100 g balls. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Proof refrigerator 12-24 hr. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Warm to room temp ≈1 hr before baking. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Shape into 7 in disc. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Let discs rest 10 min. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Bake on parchment until fully inflated. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pizza_sauce.yaml b/culinary/recipes/pizza_sauce.yaml new file mode 100644 index 0000000..43331f7 --- /dev/null +++ b/culinary/recipes/pizza_sauce.yaml @@ -0,0 +1,117 @@ +schema_version: 2 +id: pizza_sauce +revision: 1 +status: draft +title: Pizza Sauce +categories: +- sauce +tags: +- pizza +yield: + amount: + quantity: 106.91 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_puree + reference: + ingredient_id: tomato_puree + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 3.75 + unit_id: gram + percentage: 3.75 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_05_msg + reference: + ingredient_id: msg + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_06_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_07_basil + reference: + ingredient_id: basil + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_08_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_09_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_10_onion_dehydrated_mince + reference: + ingredient_id: onion_dehydrated_flake + amount: + quantity: 0.12 + unit_id: gram + percentage: 0.12 + - id: line_11_xanthan_gum + reference: + ingredient_id: xanthan_gum + amount: + quantity: 0.08 + unit_id: gram + percentage: 0.08 + - id: line_12_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.01 + unit_id: gram + percentage: 0.01 +steps: +- id: step_01 + order: 1 + instruction: Blend + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/popeyes_coater_mix.yaml b/culinary/recipes/popeyes_coater_mix.yaml new file mode 100644 index 0000000..d84cd07 --- /dev/null +++ b/culinary/recipes/popeyes_coater_mix.yaml @@ -0,0 +1,66 @@ +schema_version: 2 +id: popeyes_coater_mix +revision: 1 +status: draft +title: Popeyes Coater Mix +categories: +- component +tags: +- coater +- fried +- copycat +- popeyes +yield: + amount: + quantity: 113.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_salt + reference: + ingredient_id: salt + amount: + quantity: 7.5 + unit_id: gram + percentage: 7.5 + - id: line_03_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_04_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Whisk all dry ingredients until uniformly combined. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/popeyes_fry_batter.yaml b/culinary/recipes/popeyes_fry_batter.yaml new file mode 100644 index 0000000..fa49349 --- /dev/null +++ b/culinary/recipes/popeyes_fry_batter.yaml @@ -0,0 +1,159 @@ +schema_version: 2 +id: popeyes_fry_batter +revision: 1 +status: draft +title: Popeyes Fry Batter +categories: +- component +tags: +- batter +- fried +- copycat +- popeyes +yield: + amount: + quantity: 486.39 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 283 + unit_id: gram + percentage: 283 + - id: line_03_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 36 + unit_id: gram + percentage: 36 + - id: line_04_buttermilk_powder + reference: + ingredient_id: buttermilk_powder + amount: + quantity: 16.67 + unit_id: gram + percentage: 16.67 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 14.44 + unit_id: gram + percentage: 14.44 + - id: line_06_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 11.1 + unit_id: gram + percentage: 11.1 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 5.4 + unit_id: gram + percentage: 5.4 + - id: line_09_sugar + reference: + ingredient_id: sugar + amount: + quantity: 4.67 + unit_id: gram + percentage: 4.67 + - id: line_10_msg + reference: + ingredient_id: msg + amount: + quantity: 2.22 + unit_id: gram + percentage: 2.22 + - id: line_11_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1.33 + unit_id: gram + percentage: 1.33 + - id: line_12_garlic + reference: + ingredient_id: garlic + amount: + quantity: 0.89 + unit_id: gram + percentage: 0.89 + - id: line_13_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.67 + unit_id: gram + percentage: 0.67 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine batter dry mix. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine coater mix. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Hydrate batter w/ water. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Whisk until mostly smooth. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Coat chicken in coater mix. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Dip in batter. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Coat in coater mix again, forming clumps. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pub_pretzel.yaml b/culinary/recipes/pub_pretzel.yaml new file mode 100644 index 0000000..a3b7d9b --- /dev/null +++ b/culinary/recipes/pub_pretzel.yaml @@ -0,0 +1,132 @@ +schema_version: 2 +id: pub_pretzel +revision: 1 +status: draft +title: Pub Pretzel +categories: +- bread +tags: +- pretzel +yield: + amount: + quantity: 166.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 55 + unit_id: gram + percentage: 55 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_04_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_sugar + reference: + ingredient_id: sugar + amount: + quantity: 1.2 + unit_id: gram + percentage: 1.2 +equipment_ids: +- stand_mixer +steps: +- id: step_01 + order: 1 + instruction: Combine dry. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine wet. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add wet to mixer, then dry. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix for 10 min. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Divide into 50 g pieces. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Roll into ≈4 in logs. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Proof 1 hr 70 °F covered, misted. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Score 3x. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Bake 450 °F, 7 min. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Dip in 4% lye solution. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Finish baking in greased rack, 5 min. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Deep fry 45 sec. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pullman_white.yaml b/culinary/recipes/pullman_white.yaml new file mode 100644 index 0000000..fb24422 --- /dev/null +++ b/culinary/recipes/pullman_white.yaml @@ -0,0 +1,133 @@ +schema_version: 2 +id: pullman_white +revision: 1 +status: draft +title: Pullman White +categories: +- bread +tags: +- loaf +yield: + amount: + quantity: 190.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 65 + unit_id: gram + percentage: 65 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 9 + unit_id: gram + percentage: 9 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_08_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_09_lactic_acid_88 + reference: + ingredient_id: lactic_acid_88 + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 +equipment_ids: +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Add water, vinegar, then remaining ingredients to mixing bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix to full development. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Grease loaf pan. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Shape dough. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Place the dough seam-side down in greased pan. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Place lid on the pan, cracked slightly so that dough is visible. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Proof until dough nearly touches the lid. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Bake at 375 °F for about 32 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pumpkin_bread.yaml b/culinary/recipes/pumpkin_bread.yaml new file mode 100644 index 0000000..4a53c2c --- /dev/null +++ b/culinary/recipes/pumpkin_bread.yaml @@ -0,0 +1,82 @@ +schema_version: 2 +id: pumpkin_bread +revision: 1 +status: draft +title: Pumpkin Bread +categories: +- dessert +tags: +- quick-bread +yield: + amount: + quantity: 201 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_pumpkin_puree + reference: + ingredient_id: pumpkin_puree + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_05_water + reference: + ingredient_id: water + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pumpkin_ganache.yaml b/culinary/recipes/pumpkin_ganache.yaml new file mode 100644 index 0000000..75d1971 --- /dev/null +++ b/culinary/recipes/pumpkin_ganache.yaml @@ -0,0 +1,159 @@ +schema_version: 2 +id: pumpkin_ganache +revision: 1 +status: draft +title: Pumpkin Ganache +categories: +- sauce +tags: +- dessert-sauce +- chocolate +yield: + amount: + quantity: 207.39 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_pumpkin_puree + reference: + ingredient_id: pumpkin_puree + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_white_chocolate + reference: + ingredient_id: white_chocolate + amount: + quantity: 54 + unit_id: gram + percentage: 54 + - id: line_03_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 27.5 + unit_id: gram + percentage: 27.5 + - id: line_04_glucose + reference: + ingredient_id: glucose + amount: + quantity: 15.7 + unit_id: gram + percentage: 15.7 + - id: line_05_butter + reference: + ingredient_id: butter + amount: + quantity: 8.63 + unit_id: gram + percentage: 8.63 + - id: line_06_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.55 + unit_id: gram + percentage: 0.55 + - id: line_07_kosher_salt + reference: + ingredient_id: salt + amount: + quantity: 0.45 + unit_id: gram + percentage: 0.45 + - id: line_08_cardamom + reference: + ingredient_id: cardamom + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_09_allspice + reference: + ingredient_id: allspice + amount: + quantity: 0.12 + unit_id: gram + percentage: 0.12 + - id: line_10_ginger + reference: + ingredient_id: ginger_ground + amount: + quantity: 0.12 + unit_id: gram + percentage: 0.12 + - id: line_11_cloves + reference: + ingredient_id: cloves + amount: + quantity: 0.02 + unit_id: gram + percentage: 0.02 +equipment_ids: +- mixing_bowl +- sheet_pan +steps: +- id: step_01 + order: 1 + instruction: Spread pumpkin over parchment-lined half size baking sheet. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Roast 1 hr at 325 °F until pumpkin reduced by 40%. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add chocolate chips to a mixing bowl. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine cream, glucose, butter in pot. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Bring to the boil. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Pour over white chocolate. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Let sit for 1 min. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Add roasted pumpkin, spices, salt to mixture. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Stir, immersion blend until totally smooth. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Pour into shells warm. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/pumpkin_muffin.yaml b/culinary/recipes/pumpkin_muffin.yaml new file mode 100644 index 0000000..bf1b479 --- /dev/null +++ b/culinary/recipes/pumpkin_muffin.yaml @@ -0,0 +1,174 @@ +schema_version: 2 +id: pumpkin_muffin +revision: 1 +status: draft +title: Pumpkin Muffin +categories: +- dessert +tags: +- muffin +yield: + amount: + quantity: 403.07 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_cake + reference: + ingredient_id: flour_cake + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_pumpkin_puree + reference: + ingredient_id: pumpkin_puree + amount: + quantity: 90 + unit_id: gram + percentage: 90 + - id: line_03_brown_sugar + reference: + ingredient_id: brown_sugar + amount: + quantity: 67 + unit_id: gram + percentage: 67 + - id: line_04_chocolate_chip + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 50 + unit_id: gram + percentage: 50 + notes: chips + - id: line_05_shortening + reference: + ingredient_id: shortening + amount: + quantity: 42 + unit_id: gram + percentage: 42 + - id: line_06_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_07_water + reference: + ingredient_id: water + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_08_buttermilk_powder + reference: + ingredient_id: buttermilk_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_09_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 1.4 + unit_id: gram + percentage: 1.4 + - id: line_10_baking_soda + reference: + ingredient_id: baking_soda + amount: + quantity: 1.4 + unit_id: gram + percentage: 1.4 + - id: line_11_salt + reference: + ingredient_id: salt + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_12_ginger + reference: + ingredient_id: ginger_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_13_allspice + reference: + ingredient_id: allspice + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_14_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.17 + unit_id: gram + percentage: 0.17 + - id: line_15_nutmeg + reference: + ingredient_id: nutmeg + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +steps: +- id: step_01 + order: 1 + instruction: Combine fat, sugar, salt, spices, milk powder. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Paddle mix until light. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add eggs in 2 to 3 stages, cream well between stages. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Sift in dry ingredients. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix together liquid until combined. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add 1/4 of the dry mixture and mix until just blended. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add 1/3 of the liquid and mix until just blended. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Repeat the additions, scraping as needed. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/puppy_chow.yaml b/culinary/recipes/puppy_chow.yaml new file mode 100644 index 0000000..fc136a6 --- /dev/null +++ b/culinary/recipes/puppy_chow.yaml @@ -0,0 +1,119 @@ +schema_version: 2 +id: puppy_chow +revision: 1 +status: draft +title: Puppy Chow +categories: +- dessert +tags: +- snack +- chocolate +yield: + amount: + quantity: 562.25 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_rice_chex + reference: + ingredient_id: rice_chex + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 200 + unit_id: gram + percentage: 200 + - id: line_03_semisweet_chocolate_chips + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 150 + unit_id: gram + percentage: 150 + notes: chips + - id: line_04_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 85 + unit_id: gram + percentage: 85 + - id: line_05_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_06_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +steps: +- id: step_01 + order: 1 + instruction: Set aside rice chex. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add peanut butter, chocolate, fat, salt to pan. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Heat until melted and smooth. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Pour melted mixture over cereal. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix / fold until coated evenly. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add powdered sugar to plastic bag. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Add coated cereal to bag. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Mix in bag to coat. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/quiche_custard.yaml b/culinary/recipes/quiche_custard.yaml new file mode 100644 index 0000000..eb9240f --- /dev/null +++ b/culinary/recipes/quiche_custard.yaml @@ -0,0 +1,109 @@ +schema_version: 2 +id: quiche_custard +revision: 1 +status: draft +title: Quiche Custard +categories: +- component +tags: +- filling +- egg +yield: + amount: + quantity: 296.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 90 + unit_id: gram + percentage: 90 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 68 + unit_id: gram + percentage: 68 + - id: line_04_egg_yolk + reference: + ingredient_id: egg_yolk + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_05_milk_powder_whole + reference: + ingredient_id: milk_powder_whole + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 1.8 + unit_id: gram + percentage: 1.8 + - id: line_07_pepper + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_08_nutmeg + reference: + ingredient_id: nutmeg + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_09_xanthan_gum + reference: + ingredient_id: xanthan_gum + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Add all ingredients to blender. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend well combined. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Until ready to bake, 1 hr. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/raising_canes_sauce.yaml b/culinary/recipes/raising_canes_sauce.yaml new file mode 100644 index 0000000..e720da2 --- /dev/null +++ b/culinary/recipes/raising_canes_sauce.yaml @@ -0,0 +1,83 @@ +schema_version: 2 +id: raising_canes_sauce +revision: 1 +status: draft +title: Raising Cane's Sauce +categories: +- sauce +tags: +- copycat +- raising-canes +yield: + amount: + quantity: 183.93 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_ketchup + reference: + ingredient_id: ketchup + amount: + quantity: 70.67 + unit_id: gram + percentage: 70.67 + - id: line_03_worschestershire_sauce + reference: + ingredient_id: worschestershire_sauce + amount: + quantity: 10.67 + unit_id: gram + percentage: 10.67 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1.47 + unit_id: gram + percentage: 1.47 + - id: line_05_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.83 + unit_id: gram + percentage: 0.83 + - id: line_06_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.26 + unit_id: gram + percentage: 0.26 + - id: line_07_citric_acid + reference: + ingredient_id: citric_acid + amount: + quantity: 0.03 + unit_id: gram + percentage: 0.03 +steps: +- id: step_01 + order: 1 + instruction: Combine all. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/ranch_dressing.yaml b/culinary/recipes/ranch_dressing.yaml new file mode 100644 index 0000000..0470cfa --- /dev/null +++ b/culinary/recipes/ranch_dressing.yaml @@ -0,0 +1,55 @@ +schema_version: 2 +id: ranch_dressing +revision: 1 +status: draft +title: Ranch Dressing +categories: +- sauce +tags: +- dressing +- ranch +yield: + amount: + quantity: 228.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_milk + reference: + ingredient_id: milk + amount: + quantity: 115 + unit_id: gram + percentage: 115 + - id: line_03_ranch_powder + reference: + ingredient_id: hidden_valley_ranch_dry_seasoning + amount: + quantity: 13.6 + unit_id: gram + percentage: 13.6 +steps: +- id: step_01 + order: 1 + instruction: Mix + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/ravioli_filling.yaml b/culinary/recipes/ravioli_filling.yaml new file mode 100644 index 0000000..73dcb92 --- /dev/null +++ b/culinary/recipes/ravioli_filling.yaml @@ -0,0 +1,116 @@ +schema_version: 2 +id: ravioli_filling +revision: 1 +status: draft +title: Ravioli Filling +categories: +- meat +tags: +- ravioli +- filling +- beef +- Italian sausage +yield: + amount: + quantity: 376.55 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_ground_beef_73_27_raw + reference: + ingredient_id: ground_beef_73_27_raw + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_italian_sausage + reference: + ingredient_id: italian_sausage + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 22 + unit_id: gram + percentage: 22 + - id: line_04_mozzarella_cheese + reference: + ingredient_id: mozzarella_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_05_provolone_cheese + reference: + ingredient_id: provolone_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + - id: line_06_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_07_parsley + reference: + ingredient_id: parsley + amount: + quantity: 0.72 + unit_id: gram + percentage: 0.72 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_09_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.66 + unit_id: gram + percentage: 0.66 + - id: line_10_nutmeg + reference: + ingredient_id: nutmeg + amount: + quantity: 0.57 + unit_id: gram + percentage: 0.57 +steps: +- id: step_01 + order: 1 + instruction: Brown the beef and sausage; drain. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Process the meat and cheese for 30–60 seconds. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add the egg and seasonings; pulse until finely mixed. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/reeces_peanut_butter_cup_filling.yaml b/culinary/recipes/reeces_peanut_butter_cup_filling.yaml new file mode 100644 index 0000000..65995fc --- /dev/null +++ b/culinary/recipes/reeces_peanut_butter_cup_filling.yaml @@ -0,0 +1,56 @@ +schema_version: 2 +id: reeces_peanut_butter_cup_filling +revision: 1 +status: draft +title: Reese's Peanut Butter Cup Filling +categories: +- sauce +tags: +- filling +- copycat +- reeses +yield: + amount: + quantity: 137.7 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 37.6 + unit_id: gram + percentage: 37.6 + - id: line_03_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +steps: +- id: step_01 + order: 1 + instruction: Combine + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/refried_beans.yaml b/culinary/recipes/refried_beans.yaml new file mode 100644 index 0000000..85956bc --- /dev/null +++ b/culinary/recipes/refried_beans.yaml @@ -0,0 +1,94 @@ +schema_version: 2 +id: refried_beans +revision: 1 +status: draft +title: Refried Beans +categories: +- side +tags: +- beans +yield: + amount: + quantity: 169 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cooked_pinto_beans_drained + reference: + ingredient_id: cooked_pinto_beans_drained + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_lard + reference: + ingredient_id: lard + amount: + quantity: 6.5 + unit_id: gram + percentage: 6.5 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_05_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_06_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 + - id: line_07_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Cook beans. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine all in blender. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Blend until very smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/richs_classic_white_icing.yaml b/culinary/recipes/richs_classic_white_icing.yaml new file mode 100644 index 0000000..a344b04 --- /dev/null +++ b/culinary/recipes/richs_classic_white_icing.yaml @@ -0,0 +1,70 @@ +schema_version: 2 +id: richs_classic_white_icing +revision: 1 +status: draft +title: Rich's Classic White Icing +categories: +- sauce +tags: +- icing +- copycat +- richs +yield: + amount: + quantity: 100.095 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sugar + reference: + ingredient_id: sugar + amount: + quantity: 80 + unit_id: gram + percentage: 80 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_03_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_04_agar + reference: + ingredient_id: agar + amount: + quantity: 0.065 + unit_id: gram + percentage: 0.065 + - id: line_05_citric_acid + reference: + ingredient_id: citric_acid + amount: + quantity: 0.03 + unit_id: gram + percentage: 0.03 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/richs_maple_icing.yaml b/culinary/recipes/richs_maple_icing.yaml new file mode 100644 index 0000000..43cd7a7 --- /dev/null +++ b/culinary/recipes/richs_maple_icing.yaml @@ -0,0 +1,91 @@ +schema_version: 2 +id: richs_maple_icing +revision: 1 +status: draft +title: Rich's Maple Icing +categories: +- sauce +tags: +- icing +- copycat +- richs +yield: + amount: + quantity: 98.1835 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 68 + unit_id: gram + percentage: 68 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 11.5 + unit_id: gram + percentage: 11.5 + - id: line_03_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_04_shortening + reference: + ingredient_id: shortening + amount: + quantity: 7.5 + unit_id: gram + percentage: 7.5 + - id: line_05_maple_extract + reference: + ingredient_id: maple_extract + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_06_lecithin + reference: + ingredient_id: lecithin + amount: + quantity: 0.33 + unit_id: gram + percentage: 0.33 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 0.0535 + unit_id: gram + percentage: 0.0535 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/roasted_sweet_potato_carrot.yaml b/culinary/recipes/roasted_sweet_potato_carrot.yaml new file mode 100644 index 0000000..555a380 --- /dev/null +++ b/culinary/recipes/roasted_sweet_potato_carrot.yaml @@ -0,0 +1,96 @@ +schema_version: 2 +id: roasted_sweet_potato_carrot +revision: 1 +status: draft +title: Roasted Sweet Potato and Carrot +categories: +- side +tags: +- sweet-potato +yield: + amount: + quantity: 110.7 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_carrot + reference: + ingredient_id: carrot + amount: + quantity: 50 + unit_id: gram + percentage: 50 + basis_member: true + - id: line_01_sweet_potato + reference: + ingredient_id: sweet_potato_cooked + amount: + quantity: 50 + unit_id: gram + percentage: 50 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_03_olive_oil + reference: + ingredient_id: olive_oil + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_04_vinegar_balsamic + reference: + ingredient_id: vinegar_balsamic + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_05_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 +steps: +- id: step_01 + order: 1 + instruction: Peel, chop vegetables into 1cm^3 volume. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Soak in 5% salt solution, 4 hr. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Drain, dry. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Coat in mixture. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Roast at 400 °F for 1 hr+, stir occasionally. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/scrambled_egg_patty.yaml b/culinary/recipes/scrambled_egg_patty.yaml new file mode 100644 index 0000000..5cd2972 --- /dev/null +++ b/culinary/recipes/scrambled_egg_patty.yaml @@ -0,0 +1,90 @@ +schema_version: 2 +id: scrambled_egg_patty +revision: 1 +status: draft +title: Scrambled Egg Patty +categories: +- breakfast +tags: +- egg +yield: + amount: + quantity: 133.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 19 + unit_id: gram + percentage: 19 + - id: line_03_butter_flavored_shortening + reference: + ingredient_id: butter_flavored_shortening + amount: + quantity: 13 + unit_id: gram + percentage: 13 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_05_xanthan_gum + reference: + ingredient_id: xanthan_gum + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Combine all in blender. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Strain. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Pour into 3 in non-stick cake tin. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Bake in bain-marie until egg is set at 300 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sea_vinaigrette.yaml b/culinary/recipes/sea_vinaigrette.yaml new file mode 100644 index 0000000..9923f78 --- /dev/null +++ b/culinary/recipes/sea_vinaigrette.yaml @@ -0,0 +1,84 @@ +schema_version: 2 +id: sea_vinaigrette +revision: 1 +status: draft +title: Southeast Asian Vinaigrette +categories: +- sauce +tags: +- dressing +yield: + amount: + quantity: 343 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_orange_juice + reference: + ingredient_id: orange_juice + amount: + quantity: 110 + unit_id: gram + percentage: 110 + - id: line_03_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 75 + unit_id: gram + percentage: 75 + - id: line_04_vinegar_apple_cider + reference: + ingredient_id: vinegar_apple_cider + amount: + quantity: 37 + unit_id: gram + percentage: 37 + - id: line_05_honey + reference: + ingredient_id: honey + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_07_pepper + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 1 + unit_id: gram + percentage: 1 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Blender. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/seasoned_chicken.yaml b/culinary/recipes/seasoned_chicken.yaml new file mode 100644 index 0000000..2992feb --- /dev/null +++ b/culinary/recipes/seasoned_chicken.yaml @@ -0,0 +1,103 @@ +schema_version: 2 +id: seasoned_chicken +revision: 1 +status: draft +title: Seasoned Chicken +categories: +- meat +tags: +- chicken +- seasoning +yield: + amount: + quantity: 102.8 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_chicken + reference: + ingredient_id: chicken_breast + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_salt + reference: + ingredient_id: salt + amount: + quantity: 1.2 + unit_id: gram + percentage: 1.2 + - id: line_03_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_04_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_05_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 + - id: line_06_paprika + reference: + ingredient_id: paprika + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_07_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +steps: +- id: step_01 + order: 1 + instruction: Pat the chicken dry. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine the salt, black pepper, garlic powder, onion powder, paprika, and baking powder. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Coat the chicken evenly with the seasoning mixture. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Refrigerate uncovered for at least 1 hour, or overnight. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Roast until browned and the thickest part of the chicken reaches 165 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/shake_shack_shacksauce.yaml b/culinary/recipes/shake_shack_shacksauce.yaml new file mode 100644 index 0000000..1445cb0 --- /dev/null +++ b/culinary/recipes/shake_shack_shacksauce.yaml @@ -0,0 +1,71 @@ +schema_version: 2 +id: shake_shack_shacksauce +revision: 1 +status: draft +title: Shake Shack ShackSauce +categories: +- sauce +tags: +- copycat +- shake-shack +yield: + amount: + quantity: 135.2 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_mustard_dijon + reference: + ingredient_id: mustard_dijon + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_03_ketchup + reference: + ingredient_id: ketchup + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_pickle_juice + reference: + ingredient_id: pickle_juice + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Whisk until homogeneous. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/shakespeares_pizza_dough.yaml b/culinary/recipes/shakespeares_pizza_dough.yaml new file mode 100644 index 0000000..293f436 --- /dev/null +++ b/culinary/recipes/shakespeares_pizza_dough.yaml @@ -0,0 +1,100 @@ +schema_version: 2 +id: shakespeares_pizza_dough +revision: 1 +status: draft +title: Shakespeare's Pizza Dough +categories: +- bread +tags: +- dough +- pizza +- copycat +- shakespeares +yield: + amount: + quantity: 158.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_04_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 2 + unit_id: gram + percentage: 2 +equipment_ids: +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Add water to bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add dry. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix for 2 min. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add oil. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix until smooth, 10 to 15 min, no more than. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/shakespeares_pizza_sauce.yaml b/culinary/recipes/shakespeares_pizza_sauce.yaml new file mode 100644 index 0000000..abac7b3 --- /dev/null +++ b/culinary/recipes/shakespeares_pizza_sauce.yaml @@ -0,0 +1,105 @@ +schema_version: 2 +id: shakespeares_pizza_sauce +revision: 1 +status: draft +title: Shakespeare's Pizza Sauce +categories: +- sauce +tags: +- pizza +- copycat +- shakespeares +yield: + amount: + quantity: 111.95 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_tomato_puree + reference: + ingredient_id: tomato_puree + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 6.51 + unit_id: gram + percentage: 6.51 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1.96 + unit_id: gram + percentage: 1.96 + - id: line_05_garlic + reference: + ingredient_id: garlic + amount: + quantity: 0.27 + unit_id: gram + percentage: 0.27 + - id: line_06_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_07_black_pepper_ground + reference: + ingredient_id: black_pepper_ground + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 + - id: line_08_sugar + reference: + ingredient_id: sugar + amount: + quantity: 0.17 + unit_id: gram + percentage: 0.17 + - id: line_09_onion + reference: + ingredient_id: onion_yellow + amount: + quantity: 0.08 + unit_id: gram + percentage: 0.08 + - id: line_10_cayenne + reference: + ingredient_id: cayenne + amount: + quantity: 0.01 + unit_id: gram + percentage: 0.01 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sour_cream.yaml b/culinary/recipes/sour_cream.yaml new file mode 100644 index 0000000..f0a725a --- /dev/null +++ b/culinary/recipes/sour_cream.yaml @@ -0,0 +1,54 @@ +schema_version: 2 +id: sour_cream +revision: 1 +status: draft +title: Sour Cream +categories: +- component +tags: +- base-formula +yield: + amount: + quantity: 121.8 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cream_cheese + reference: + ingredient_id: cream_cheese + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 21.8 + unit_id: gram + percentage: 21.8 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Add to blender. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sourdough.yaml b/culinary/recipes/sourdough.yaml new file mode 100644 index 0000000..927b360 --- /dev/null +++ b/culinary/recipes/sourdough.yaml @@ -0,0 +1,164 @@ +schema_version: 2 +id: sourdough +revision: 1 +status: draft +title: Sourdough +categories: +- bread +tags: +- sourdough +- loaf +yield: + amount: + quantity: 179.3 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 71.8 + unit_id: gram + percentage: 71.8 + - id: line_03_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 2.3 + unit_id: gram + percentage: 2.3 + - id: line_05_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_06_lactic_acid_88 + reference: + ingredient_id: lactic_acid_88 + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 +equipment_ids: +- mixing_bowl +- oven +steps: +- id: step_01 + order: 1 + instruction: Dissolve lactic acid, vinegar, ascorbic acid into water. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add liquid to mixing bowl, reserve 10% + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add dry to mixing bowl. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Remove dough, divide 500 g balls. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Rest 10 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Form into ball, flour ball. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Place into banneton. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Proof. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Preheat baking steel 3/8 in for 1 hr, middle rack at 500 °F. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Turn out onto parchment, pizza peel. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Launch into oven. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Lower temp. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Bake 8 min. + component_ids: + - main +- id: step_15 + order: 15 + instruction: Remove loaf, place on rack, back in oven. + component_ids: + - main +- id: step_16 + order: 16 + instruction: Bake 12 min. + component_ids: + - main +- id: step_17 + order: 17 + instruction: Drop temp. + component_ids: + - main +- id: step_18 + order: 18 + instruction: Bake 12 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sourdough_starter.yaml b/culinary/recipes/sourdough_starter.yaml new file mode 100644 index 0000000..47a01ab --- /dev/null +++ b/culinary/recipes/sourdough_starter.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: sourdough_starter +revision: 1 +status: active +title: Sourdough Starter, 100% Hydration +categories: +- component +tags: +- sourdough +- preferment +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 50 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 50 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 100 +steps: +- id: step_01 + order: 1 + instruction: Mix equal weights of bread flour and water with an established culture and ferment until active. + component_ids: + - main +notes: +- This is a 100% hydration maintenance formula; fermentation loss is not yet modeled. diff --git a/culinary/recipes/spritz_cookie.yaml b/culinary/recipes/spritz_cookie.yaml new file mode 100644 index 0000000..71656a7 --- /dev/null +++ b/culinary/recipes/spritz_cookie.yaml @@ -0,0 +1,126 @@ +schema_version: 2 +id: spritz_cookie +revision: 1 +status: draft +title: Spritz Cookie +categories: +- dessert +tags: +- cookie +yield: + amount: + quantity: 254.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_shortening + reference: + ingredient_id: shortening + amount: + quantity: 73 + unit_id: gram + percentage: 73 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 58 + unit_id: gram + percentage: 58 + - id: line_04_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_05_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_07_almond_extract + reference: + ingredient_id: almond_extract + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 0.5 + unit_id: gram + percentage: 0.5 +equipment_ids: +- mixing_bowl +steps: +- id: step_01 + order: 1 + instruction: Cream shortening, adding sugar in gradually. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add egg, dry mix, extract. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix well. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Fill cookie press. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Form cookies on cookie sheet. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Bake 6 min at 400 °F. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Place the fat, sugar, salt, and spices in the mixing bowl. + component_ids: + - main +- id: step_08 + order: 8 + instruction: With the paddle attachment, cream these ingredients at low speed. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/srirancha.yaml b/culinary/recipes/srirancha.yaml new file mode 100644 index 0000000..d49a7de --- /dev/null +++ b/culinary/recipes/srirancha.yaml @@ -0,0 +1,62 @@ +schema_version: 2 +id: srirancha +revision: 1 +status: draft +title: Srirancha +categories: +- sauce +tags: +- dressing +- ranch +yield: + amount: + quantity: 243.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_milk + reference: + ingredient_id: milk + amount: + quantity: 115 + unit_id: gram + percentage: 115 + - id: line_03_sriracha + reference: + ingredient_id: sriracha + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_ranch_powder + reference: + ingredient_id: hidden_valley_ranch_dry_seasoning + amount: + quantity: 13.6 + unit_id: gram + percentage: 13.6 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/starch_glaze.yaml b/culinary/recipes/starch_glaze.yaml new file mode 100644 index 0000000..5d0662e --- /dev/null +++ b/culinary/recipes/starch_glaze.yaml @@ -0,0 +1,60 @@ +schema_version: 2 +id: starch_glaze +revision: 1 +status: draft +title: Starch Glaze +categories: +- component +tags: +- glaze +yield: + amount: + quantity: 104 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_tapioca_starch + reference: + ingredient_id: tapioca_starch + amount: + quantity: 4 + unit_id: gram + percentage: 4 +equipment_ids: +- mixing_bowl +- whisk +steps: +- id: step_01 + order: 1 + instruction: Whisk to combine in bowl. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Heat until thickened. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Apply to bread just before baking. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/steamed_eggs.yaml b/culinary/recipes/steamed_eggs.yaml new file mode 100644 index 0000000..b4bc469 --- /dev/null +++ b/culinary/recipes/steamed_eggs.yaml @@ -0,0 +1,85 @@ +schema_version: 2 +id: steamed_eggs +revision: 1 +status: draft +title: Steamed Eggs +categories: +- breakfast +tags: +- egg +yield: + amount: + quantity: 133.3 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 19 + unit_id: gram + percentage: 19 + - id: line_03_fat + reference: + ingredient_id: canola_oil + amount: + quantity: 13 + unit_id: gram + percentage: 13 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_05_xanthan_gum + reference: + ingredient_id: xanthan_gum + amount: + quantity: 0.2 + unit_id: gram + percentage: 0.2 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Add to blender. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Strain. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Pour 90g in mini cake tin. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/subway_italian.yaml b/culinary/recipes/subway_italian.yaml new file mode 100644 index 0000000..af4828c --- /dev/null +++ b/culinary/recipes/subway_italian.yaml @@ -0,0 +1,151 @@ +schema_version: 2 +id: subway_italian +revision: 1 +status: draft +title: Subway Italian +categories: +- bread +tags: +- loaf +- copycat +- subway +yield: + amount: + quantity: 176 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 4.7 + unit_id: gram + percentage: 4.7 + - id: line_04_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 4.5 + unit_id: gram + percentage: 4.5 + - id: line_05_wheat_gluten_70_80 + reference: + ingredient_id: wheat_gluten_70_80 + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_06_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1.8 + unit_id: gram + percentage: 1.8 +equipment_ids: +- oven +steps: +- id: step_01 + order: 1 + instruction: Combine dry and mix well. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add water, then dry. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix ≈5 min until combined. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add oil. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to ≈20 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Rest 10 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Divide into 175 g balls. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Roll into 12 in sticks. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Grease pan. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Place sticks in pan. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Spray sticks with water. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Proof in pan 1 hr 30 min at 85 °F, humid, oven light. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Remove, from oven, preheat. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Bake ≈15 min at 350 °F, middle rack. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/subway_whole_wheat.yaml b/culinary/recipes/subway_whole_wheat.yaml new file mode 100644 index 0000000..32bc2c3 --- /dev/null +++ b/culinary/recipes/subway_whole_wheat.yaml @@ -0,0 +1,160 @@ +schema_version: 2 +id: subway_whole_wheat +revision: 1 +status: draft +title: Subway Whole Wheat +categories: +- bread +tags: +- loaf +- copycat +- subway +yield: + amount: + quantity: 173 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_whole_wheat + reference: + ingredient_id: flour_whole_wheat + amount: + quantity: 46 + unit_id: gram + percentage: 46 + basis_member: true + - id: line_02_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 31 + unit_id: gram + percentage: 31 + basis_member: true + - id: line_03_wheat_gluten_70_80 + reference: + ingredient_id: wheat_gluten_70_80 + amount: + quantity: 23 + unit_id: gram + percentage: 23 + basis_member: true + - id: line_04_water + reference: + ingredient_id: water + amount: + quantity: 60 + unit_id: gram + percentage: 60 + - id: line_05_sugar + reference: + ingredient_id: sugar + amount: + quantity: 4.7 + unit_id: gram + percentage: 4.7 + - id: line_06_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 4.5 + unit_id: gram + percentage: 4.5 + - id: line_07_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 1.8 + unit_id: gram + percentage: 1.8 +equipment_ids: +- oven +steps: +- id: step_01 + order: 1 + instruction: Combine dry and mix well. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add water, then dry. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix ≈5 min until combined. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add oil. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to ≈20 min. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Rest 10 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Divide into 180 g balls. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Roll into 12 in sticks. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Grease pan. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Place sticks in pan. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Spray sticks with water. + component_ids: + - main +- id: step_12 + order: 12 + instruction: Proof in pan 1 hr 30 min at 85 °F, humid, oven light. + component_ids: + - main +- id: step_13 + order: 13 + instruction: Remove, from oven, preheat. + component_ids: + - main +- id: step_14 + order: 14 + instruction: Bake ≈15 min at 350 °F, middle rack. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sushi_rice.yaml b/culinary/recipes/sushi_rice.yaml new file mode 100644 index 0000000..5c4f533 --- /dev/null +++ b/culinary/recipes/sushi_rice.yaml @@ -0,0 +1,85 @@ +schema_version: 2 +id: sushi_rice +revision: 1 +status: draft +title: Sushi Rice +categories: +- side +tags: +- rice +yield: + amount: + quantity: 279.9 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_rice + reference: + ingredient_id: rice + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 150 + unit_id: gram + percentage: 150 + - id: line_03_vinegar_rice + reference: + ingredient_id: vinegar_rice + amount: + quantity: 16.5 + unit_id: gram + percentage: 16.5 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 3.4 + unit_id: gram + percentage: 3.4 + - id: line_06_msg + reference: + ingredient_id: msg + amount: + quantity: 0 + unit_id: gram + percentage: 0 +steps: +- id: step_01 + order: 1 + instruction: Cook rice in rice cooker. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix, dissolve salt, msg, sugar into rice vinegar. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add seasoning liquid to cooked rice. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sweet_hawaiian_rolls.yaml b/culinary/recipes/sweet_hawaiian_rolls.yaml new file mode 100644 index 0000000..e09f9da --- /dev/null +++ b/culinary/recipes/sweet_hawaiian_rolls.yaml @@ -0,0 +1,148 @@ +schema_version: 2 +id: sweet_hawaiian_rolls +revision: 1 +status: draft +title: Sweet Hawaiian Rolls +categories: +- bread +tags: +- roll +yield: + amount: + quantity: 224.42 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_bread + reference: + ingredient_id: flour_bread + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 55 + unit_id: gram + percentage: 55 + - id: line_03_sugar + reference: + ingredient_id: sugar + amount: + quantity: 28 + unit_id: gram + percentage: 28 + - id: line_04_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 18 + unit_id: gram + percentage: 18 + - id: line_05_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 12 + unit_id: gram + percentage: 12 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 5.25 + unit_id: gram + percentage: 5.25 + - id: line_07_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 3.5 + unit_id: gram + percentage: 3.5 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_09_lecithin_powder + reference: + ingredient_id: lecithin_powder + amount: + quantity: 0.67 + unit_id: gram + percentage: 0.67 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine, whisk dry ingredients, except sugar. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine, whisk wet ingredients, except oil. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Mix to moderate gluten development. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add sugar, in stages. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to full gluten development. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Add oil, slowly. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Mix until dough is smooth, glossy, full gluten development again. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Form into ≈35 g balls. + component_ids: + - main +- id: step_09 + order: 9 + instruction: Arrange on greased, optionally parchment-lined 13 in × 9 in pan. + component_ids: + - main +- id: step_10 + order: 10 + instruction: Proof covered. + component_ids: + - main +- id: step_11 + order: 11 + instruction: Bake ≈16 min at 350 °F. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sweet_potato_hummus.yaml b/culinary/recipes/sweet_potato_hummus.yaml new file mode 100644 index 0000000..d965bf8 --- /dev/null +++ b/culinary/recipes/sweet_potato_hummus.yaml @@ -0,0 +1,104 @@ +schema_version: 2 +id: sweet_potato_hummus +revision: 1 +status: draft +title: Sweet Potato Hummus +categories: +- side +tags: +- hummus +- sweet-potato +yield: + amount: + quantity: 129.45 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sweet_potato_cooked + reference: + ingredient_id: sweet_potato_cooked + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 10 + unit_id: gram + percentage: 10 + - id: line_03_tahini + reference: + ingredient_id: tahini + amount: + quantity: 8.5 + unit_id: gram + percentage: 8.5 + - id: line_04_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1.75 + unit_id: gram + percentage: 1.75 + - id: line_06_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_07_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_08_zaatar + reference: + ingredient_id: zaatar + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_09_chipotle_pepper + reference: + ingredient_id: chipotle_powder + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +equipment_ids: +- blender +steps: +- id: step_01 + order: 1 + instruction: Combine ingredients in blender. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Blend until smooth. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sweet_roll.yaml b/culinary/recipes/sweet_roll.yaml new file mode 100644 index 0000000..d542e15 --- /dev/null +++ b/culinary/recipes/sweet_roll.yaml @@ -0,0 +1,89 @@ +schema_version: 2 +id: sweet_roll +revision: 1 +status: draft +title: Sweet Roll +categories: +- bread +tags: +- roll +yield: + amount: + quantity: 214.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 40 + unit_id: gram + percentage: 40 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_05_egg_whole + reference: + ingredient_id: egg_whole + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_07_instant_yeast + reference: + ingredient_id: instant_yeast + amount: + quantity: 2.6 + unit_id: gram + percentage: 2.6 + - id: line_08_salt + reference: + ingredient_id: salt + amount: + quantity: 2 + unit_id: gram + percentage: 2 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/sweet_sour_sauce.yaml b/culinary/recipes/sweet_sour_sauce.yaml new file mode 100644 index 0000000..36bee7a --- /dev/null +++ b/culinary/recipes/sweet_sour_sauce.yaml @@ -0,0 +1,82 @@ +schema_version: 2 +id: sweet_sour_sauce +revision: 1 +status: draft +title: Sweet & Sour Sauce +categories: +- sauce +tags: +- chinese +yield: + amount: + quantity: 239.03 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_water + reference: + ingredient_id: water + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 80 + unit_id: gram + percentage: 80 + - id: line_03_vinegar_5 + reference: + ingredient_id: vinegar_5 + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1.2 + unit_id: gram + percentage: 1.2 + - id: line_06_msg + reference: + ingredient_id: msg + amount: + quantity: 0.83 + unit_id: gram + percentage: 0.83 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Combine all in sauce pot. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Whisk and bring to boil until thick. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/taco_bell_refried_beans.yaml b/culinary/recipes/taco_bell_refried_beans.yaml new file mode 100644 index 0000000..8aeafcf --- /dev/null +++ b/culinary/recipes/taco_bell_refried_beans.yaml @@ -0,0 +1,89 @@ +schema_version: 2 +id: taco_bell_refried_beans +revision: 1 +status: draft +title: Taco Bell Refried Beans +categories: +- side +tags: +- beans +- copycat +- taco-bell +yield: + amount: + quantity: 154 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_cooked_pinto_beans_drained + reference: + ingredient_id: cooked_pinto_beans_drained + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 30 + unit_id: gram + percentage: 30 + - id: line_03_lard + reference: + ingredient_id: lard + amount: + quantity: 18 + unit_id: gram + percentage: 18 + - id: line_04_salt + reference: + ingredient_id: salt + amount: + quantity: 5 + unit_id: gram + percentage: 5 + - id: line_05_lime_juice + reference: + ingredient_id: lime_juice + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_06_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 + - id: line_07_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +steps: +- id: step_01 + order: 1 + instruction: Cook beans + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mash with remaining ingredients + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/taco_bell_seasoned_beef.yaml b/culinary/recipes/taco_bell_seasoned_beef.yaml new file mode 100644 index 0000000..683b2d9 --- /dev/null +++ b/culinary/recipes/taco_bell_seasoned_beef.yaml @@ -0,0 +1,134 @@ +schema_version: 2 +id: taco_bell_seasoned_beef +revision: 1 +status: draft +title: Taco Bell Seasoned Beef +categories: +- meat +tags: +- beef +- copycat +- taco-bell +yield: + amount: + quantity: 107.13 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_ground_beef_73_27_raw + reference: + ingredient_id: ground_beef_73_27_raw + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_oats + reference: + ingredient_id: oats + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_03_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_04_cocoa_powder + reference: + ingredient_id: cocoa_powder + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 + - id: line_05_tomato_bouillon + reference: + ingredient_id: tomato_bouillon + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 + - id: line_06_chili_powder + reference: + ingredient_id: chili_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_07_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 0.33 + unit_id: gram + percentage: 0.33 + - id: line_08_sugar + reference: + ingredient_id: sugar + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_09_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_10_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_11_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 +equipment_ids: +- whisk +steps: +- id: step_01 + order: 1 + instruction: Boil beef until cooked. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Drain beef; set aside. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine, whisk dry ingredients and small amount of cold water (enough dissolve sugar, salt). + component_ids: + - main +- id: step_04 + order: 4 + instruction: Combine beef and slurry in pan. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Heat, stirring until thickened slightly. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml b/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml new file mode 100644 index 0000000..b626ffd --- /dev/null +++ b/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml @@ -0,0 +1,132 @@ +schema_version: 2 +id: taco_bell_slow_roasted_shredded_chicken +revision: 1 +status: draft +title: Taco Bell Slow Roasted Shredded Chicken +categories: +- meat +tags: +- chicken +- copycat +- taco-bell +yield: + amount: + quantity: 128.6 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_chicken_breast + reference: + ingredient_id: chicken_breast + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 21 + unit_id: gram + percentage: 21 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 2.5 + unit_id: gram + percentage: 2.5 + - id: line_04_cornstarch + reference: + ingredient_id: cornstarch + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 + - id: line_06_tomato_bouillon + reference: + ingredient_id: tomato_bouillon + amount: + quantity: 0.7 + unit_id: gram + percentage: 0.7 + - id: line_07_chili_powder + reference: + ingredient_id: chili_powder + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_08_sugar + reference: + ingredient_id: sugar + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_09_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_10_garlic_powder + reference: + ingredient_id: garlic_powder + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 + - id: line_11_cumin + reference: + ingredient_id: cumin + amount: + quantity: 0.25 + unit_id: gram + percentage: 0.25 +steps: +- id: step_01 + order: 1 + instruction: Poach or braise chicken in water (ingredient listed), ≈180 °F for 1 hr. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add to mixing bow with paddle attachment, shred. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine cold water, remaining ingredients. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add to pan with chicken. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Heat until thickened. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/tangzhong.yaml b/culinary/recipes/tangzhong.yaml new file mode 100644 index 0000000..b2d1c18 --- /dev/null +++ b/culinary/recipes/tangzhong.yaml @@ -0,0 +1,58 @@ +schema_version: 2 +id: tangzhong +revision: 1 +status: active +title: Tangzhong +categories: [component] +tags: [bread, preferment] +yield: + amount: + quantity: 600 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: flour_basis + basis_amount: + quantity: 100 + unit_id: gram +components: + - id: main + name: Tangzhong + items: + - id: flour + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: water + reference: + ingredient_id: water + amount: + quantity: 500 + unit_id: gram + percentage: 500 +equipment_ids: +- saucepan +- whisk +steps: + - id: combine + order: 1 + instruction: Whisk the flour and water together in a saucepan. + component_ids: [main] + item_ids: [flour, water] + - id: cook + order: 2 + instruction: Cook over medium-low heat, stirring constantly, until thickened and the mixture reaches 65 °C. + component_ids: [main] + temperature: + quantity: 65 + unit_id: celsius + - id: cool + order: 3 + instruction: Remove from the heat, cover the surface directly, and cool before using. +notes: + - The theoretical yield assumes no measured cooking loss; replace it with an observed finished weight when available. diff --git a/culinary/recipes/texas_roadhouse_honey_butter.yaml b/culinary/recipes/texas_roadhouse_honey_butter.yaml new file mode 100644 index 0000000..1fcc07c --- /dev/null +++ b/culinary/recipes/texas_roadhouse_honey_butter.yaml @@ -0,0 +1,71 @@ +schema_version: 2 +id: texas_roadhouse_honey_butter +revision: 1 +status: draft +title: Texas Roadhouse Honey Butter +categories: +- sauce +tags: +- spread +- copycat +- texas-roadhouse +yield: + amount: + quantity: 120.1 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_butter + reference: + ingredient_id: butter + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_honey + reference: + ingredient_id: honey + amount: + quantity: 20 + unit_id: gram + percentage: 20 + - id: line_03_cinnamon + reference: + ingredient_id: cinnamon + amount: + quantity: 0.1 + unit_id: gram + percentage: 0.1 +steps: +- id: step_01 + order: 1 + instruction: Whip butter low, 5 min. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Add honey, cinnamon. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whip medium 5 min. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Whip high 5 min. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/top_pot_chocolate_icing.yaml b/culinary/recipes/top_pot_chocolate_icing.yaml new file mode 100644 index 0000000..90c88de --- /dev/null +++ b/culinary/recipes/top_pot_chocolate_icing.yaml @@ -0,0 +1,93 @@ +schema_version: 2 +id: top_pot_chocolate_icing +revision: 1 +status: draft +title: Top Pot Chocolate Icing +categories: +- sauce +tags: +- icing +- chocolate +- copycat +- top-pot +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_confectioners_sugar + reference: + ingredient_id: confectioners_sugar + amount: + quantity: 57.27 + unit_id: gram + percentage: 57.27 + basis_member: true + - id: line_02_chocolate_chip + reference: + ingredient_id: semisweet_chocolate + amount: + quantity: 20.6 + unit_id: gram + percentage: 20.6 + notes: chips + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 16.04 + unit_id: gram + percentage: 16.04 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 2.86 + unit_id: gram + percentage: 2.86 + - id: line_05_corn_syrup + reference: + ingredient_id: corn_syrup_light + amount: + quantity: 2.18 + unit_id: gram + percentage: 2.18 + - id: line_06_salt + reference: + ingredient_id: salt + amount: + quantity: 0.4 + unit_id: gram + percentage: 0.4 + - id: line_07_vanilla_extract + reference: + ingredient_id: vanilla_extract + amount: + quantity: 0.36 + unit_id: gram + percentage: 0.36 + - id: line_08_agar + reference: + ingredient_id: agar + amount: + quantity: 0.29 + unit_id: gram + percentage: 0.29 +steps: +- id: step_01 + order: 1 + instruction: 'TODO: Add complete preparation instructions for this recipe.' + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/tortilla.yaml b/culinary/recipes/tortilla.yaml new file mode 100644 index 0000000..a9a95bf --- /dev/null +++ b/culinary/recipes/tortilla.yaml @@ -0,0 +1,109 @@ +schema_version: 2 +id: tortilla +revision: 1 +status: draft +title: Tortilla +categories: +- bread +tags: [] +yield: + amount: + quantity: 163.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_all_purpose + reference: + ingredient_id: flour_all_purpose + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_shortening + reference: + ingredient_id: shortening + amount: + quantity: 9 + unit_id: gram + percentage: 9 + - id: line_04_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_05_salt + reference: + ingredient_id: salt + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 1.5 + unit_id: gram + percentage: 1.5 +steps: +- id: step_01 + order: 1 + instruction: Combine all but oil. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Mix til combined. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Add oil. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Mix 30 min total. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Divide into dough balls. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Rest balls 15 min. + component_ids: + - main +- id: step_07 + order: 7 + instruction: Bake 375 - 450 °F, 20-60 sec, making steel. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Allow to cool to 85 °F before packaging. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/turkish_herb_sauce.yaml b/culinary/recipes/turkish_herb_sauce.yaml new file mode 100644 index 0000000..efdc114 --- /dev/null +++ b/culinary/recipes/turkish_herb_sauce.yaml @@ -0,0 +1,117 @@ +schema_version: 2 +id: turkish_herb_sauce +revision: 1 +status: draft +title: Turkish Herb Sauce +categories: +- sauce +tags: +- turkish +yield: + amount: + quantity: 183.55 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_mayonnaise + reference: + ingredient_id: mayonnaise + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_yogurt + reference: + ingredient_id: yogurt + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_03_water + reference: + ingredient_id: water + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_04_sugar + reference: + ingredient_id: sugar + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_05_lemon_juice + reference: + ingredient_id: lemon_juice + amount: + quantity: 3.8 + unit_id: gram + percentage: 3.8 + - id: line_06_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 2 + unit_id: gram + percentage: 2 + - id: line_07_salt + reference: + ingredient_id: salt + amount: + quantity: 1.2 + unit_id: gram + percentage: 1.2 + - id: line_08_onion_powder + reference: + ingredient_id: onion_powder + amount: + quantity: 1.1 + unit_id: gram + percentage: 1.1 + - id: line_09_dill + reference: + ingredient_id: dill + amount: + quantity: 0.8 + unit_id: gram + percentage: 0.8 + - id: line_10_mint + reference: + ingredient_id: mint_dried + amount: + quantity: 0.75 + unit_id: gram + percentage: 0.75 + - id: line_11_oregano + reference: + ingredient_id: oregano + amount: + quantity: 0.6 + unit_id: gram + percentage: 0.6 + - id: line_12_msg + reference: + ingredient_id: msg + amount: + quantity: 0.3 + unit_id: gram + percentage: 0.3 +steps: +- id: step_01 + order: 1 + instruction: Mix. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/udon_noodle_sauce.yaml b/culinary/recipes/udon_noodle_sauce.yaml new file mode 100644 index 0000000..709779b --- /dev/null +++ b/culinary/recipes/udon_noodle_sauce.yaml @@ -0,0 +1,90 @@ +schema_version: 2 +id: udon_noodle_sauce +revision: 1 +status: draft +title: Udon Noodle Sauce +categories: +- soup +tags: +- thai +- noodle +yield: + amount: + quantity: 195.92 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_coconut_milk + reference: + ingredient_id: coconut_milk + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 66.67 + unit_id: gram + percentage: 66.67 + - id: line_03_peanut_butter + reference: + ingredient_id: peanut_butter + amount: + quantity: 11 + unit_id: gram + percentage: 11 + - id: line_04_red_curry_paste + reference: + ingredient_id: red_curry_paste + amount: + quantity: 7 + unit_id: gram + percentage: 7 + - id: line_05_soy_sauce_light_low_sodium + reference: + ingredient_id: soy_sauce_light_low_sodium + amount: + quantity: 4 + unit_id: gram + percentage: 4 + - id: line_06_chicken_base + reference: + ingredient_id: chicken_base + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 3 + unit_id: gram + percentage: 3 + - id: line_08_garlic_dehydrated_minced + reference: + ingredient_id: garlic_dehydrated_minced + amount: + quantity: 1.25 + unit_id: gram + percentage: 1.25 +steps: +- id: step_01 + order: 1 + instruction: Combine. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/waffles.yaml b/culinary/recipes/waffles.yaml new file mode 100644 index 0000000..3579335 --- /dev/null +++ b/culinary/recipes/waffles.yaml @@ -0,0 +1,121 @@ +schema_version: 2 +id: waffles +revision: 1 +status: draft +title: Waffles +categories: +- breakfast +tags: +- batter +yield: + amount: + quantity: 382.5 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_flour_pastry + reference: + ingredient_id: flour_pastry + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_water + reference: + ingredient_id: water + amount: + quantity: 135 + unit_id: gram + percentage: 135 + - id: line_03_oil + reference: + ingredient_id: canola_oil + amount: + quantity: 50 + unit_id: gram + percentage: 50 + - id: line_04_egg_whites + reference: + ingredient_id: egg_whites + amount: + quantity: 38 + unit_id: gram + percentage: 38 + - id: line_05_egg_yolk + reference: + ingredient_id: egg_yolk + amount: + quantity: 25 + unit_id: gram + percentage: 25 + - id: line_06_nonfat_milk_powder + reference: + ingredient_id: nonfat_milk_powder + amount: + quantity: 15 + unit_id: gram + percentage: 15 + - id: line_07_sugar + reference: + ingredient_id: sugar + amount: + quantity: 12.5 + unit_id: gram + percentage: 12.5 + - id: line_08_baking_powder + reference: + ingredient_id: baking_powder + amount: + quantity: 6 + unit_id: gram + percentage: 6 + - id: line_09_salt + reference: + ingredient_id: salt + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Sift together flour, salt, baking powder. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Combine egg yolks, water, milk powder, fat. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Whip egg whites to soft peaks. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Add sugar and beat until stiff peak. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Mix to just combined. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Fold in meringue. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/whipped_cream.yaml b/culinary/recipes/whipped_cream.yaml new file mode 100644 index 0000000..6211b69 --- /dev/null +++ b/culinary/recipes/whipped_cream.yaml @@ -0,0 +1,89 @@ +schema_version: 2 +id: whipped_cream +revision: 1 +status: draft +title: Whipped Cream +categories: +- sauce +tags: +- dessert-sauce +yield: + amount: + quantity: 109 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100.0 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_heavy_cream + reference: + ingredient_id: heavy_cream + amount: + quantity: 100 + unit_id: gram + percentage: 100 + basis_member: true + - id: line_02_sugar + reference: + ingredient_id: sugar + amount: + quantity: 8 + unit_id: gram + percentage: 8 + - id: line_03_gelatin + reference: + ingredient_id: gelatin + amount: + quantity: 1 + unit_id: gram + percentage: 1 +steps: +- id: step_01 + order: 1 + instruction: Whip 80% amount heavy cream mixture to soft peaks. + component_ids: + - main +- id: step_02 + order: 2 + instruction: Reserve this cold. + component_ids: + - main +- id: step_03 + order: 3 + instruction: Combine remaining 20% heavy cream with sugar, gelatin. + component_ids: + - main +- id: step_04 + order: 4 + instruction: Allow gelatin to bloom 6 min. + component_ids: + - main +- id: step_05 + order: 5 + instruction: Heat to 125 °F. + component_ids: + - main +- id: step_06 + order: 6 + instruction: Remove from heat + component_ids: + - main +- id: step_07 + order: 7 + instruction: Stream into cold whipped cream, whipping on medium speed. + component_ids: + - main +- id: step_08 + order: 8 + instruction: Finish incorporating with spatula. + component_ids: + - main +notes: +- Formula uses a nominal 100 g basis; review yield and revision before activation. diff --git a/culinary/recipes/white_cheddar_parmesan_blend.yaml b/culinary/recipes/white_cheddar_parmesan_blend.yaml new file mode 100644 index 0000000..fdd1aef --- /dev/null +++ b/culinary/recipes/white_cheddar_parmesan_blend.yaml @@ -0,0 +1,48 @@ +schema_version: 2 +id: white_cheddar_parmesan_blend +revision: 1 +status: active +title: White Cheddar–Parmesan Blend +categories: +- component +tags: +- cheese +- blend +yield: + amount: + quantity: 100 + unit_id: gram + basis: theoretical +scaling: + mode: hybrid + basis_id: formula_basis + basis_amount: + quantity: 100 + unit_id: gram +components: +- id: main + name: Main + items: + - id: line_01_sharp_cheddar_cheese + reference: + ingredient_id: sharp_cheddar_cheese + amount: + quantity: 80 + unit_id: gram + percentage: 80 + basis_member: true + - id: line_02_parmesan_cheese + reference: + ingredient_id: parmesan_cheese + amount: + quantity: 20 + unit_id: gram + percentage: 20 +steps: +- id: step_01 + order: 1 + instruction: Grate the cheddar and combine thoroughly with the grated Parmesan. + component_ids: + - main +notes: +- The initial formulation is 80% sharp white cheddar and 20% dry grated Parmesan by weight. diff --git a/culinary/source_mappings/supplier_label_lee_kum_kee_premium_dark_soy_sauce_078895126389.yaml b/culinary/source_mappings/supplier_label_lee_kum_kee_premium_dark_soy_sauce_078895126389.yaml new file mode 100644 index 0000000..79a85aa --- /dev/null +++ b/culinary/source_mappings/supplier_label_lee_kum_kee_premium_dark_soy_sauce_078895126389.yaml @@ -0,0 +1,23 @@ +schema_version: 2 +id: supplier_label_lee_kum_kee_premium_dark_soy_sauce_078895126389 +subject: + type: ingredient + id: soy_sauce_dark +mapping_type: nutrition +status: reviewed +source: + source_type: supplier + external_id: '078895126389' + url: https://www.heb.com/product-detail/lee-kum-kee-dark-soy-sauce/2241082 + title: Lee Kum Kee Premium Dark Soy Sauce nutrition label + publisher: H-E-B + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' + notes: U.S. retail label for UPC 078895126389. Values converted from a 15 g serving to 100 g; label rounding is therefore preserved and amplified. +nutrition_per_100g: + energy_kcal: 166.6667 + total_fat_g: 0.0 + carbohydrate_g: 33.3333 + total_sugars_g: 20.0 + sodium_mg: 7733.3333 diff --git a/culinary/source_mappings/usda_fdc_agar_170090.yaml b/culinary/source_mappings/usda_fdc_agar_170090.yaml new file mode 100644 index 0000000..97b58e5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_agar_170090.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_agar_170090 +subject: + type: ingredient + id: agar +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170090' + url: https://fdc.nal.usda.gov/food-details/170090/nutrients + title: Seaweed, agar, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170090 + data_type: SR Legacy + description: Seaweed, agar, dried +nutrition_per_100g: + calcium_mg: 625 + carbohydrate_g: 80.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 7.7 + energy_kcal: 306 + iron_mg: 21.4 + potassium_mg: 1120.0 + protein_g: 6.21 + saturated_fat_g: 0.061 + sodium_mg: 102 + total_fat_g: 0.3 + total_sugars_g: 2.97 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_allspice_171315.yaml b/culinary/source_mappings/usda_fdc_allspice_171315.yaml new file mode 100644 index 0000000..7996883 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_allspice_171315.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_allspice_171315 +subject: + type: ingredient + id: allspice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171315' + url: https://fdc.nal.usda.gov/food-details/171315/nutrients + title: Spices, allspice, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171315 + data_type: SR Legacy + description: Spices, allspice, ground +nutrition_per_100g: + calcium_mg: 661 + carbohydrate_g: 72.1 + cholesterol_mg: 0.0 + dietary_fiber_g: 21.6 + energy_kcal: 263 + iron_mg: 7.06 + potassium_mg: 1040.0 + protein_g: 6.09 + saturated_fat_g: 2.55 + sodium_mg: 77.0 + total_fat_g: 8.69 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_apricot_jam_170645.yaml b/culinary/source_mappings/usda_fdc_apricot_jam_170645.yaml new file mode 100644 index 0000000..8d817d4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_apricot_jam_170645.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_apricot_jam_170645 +subject: + type: ingredient + id: apricot_jam +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170645' + url: https://fdc.nal.usda.gov/food-details/170645/nutrients + title: Jams and preserves, apricot + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170645 + data_type: SR Legacy + description: Jams and preserves, apricot +nutrition_per_100g: + calcium_mg: 20.0 + carbohydrate_g: 64.4 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.3 + energy_kcal: 242 + iron_mg: 0.49 + potassium_mg: 77.0 + protein_g: 0.7 + saturated_fat_g: 0.01 + sodium_mg: 40.0 + total_fat_g: 0.2 + total_sugars_g: 43.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_avocado_2710824.yaml b/culinary/source_mappings/usda_fdc_avocado_2710824.yaml new file mode 100644 index 0000000..1bcbd76 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_avocado_2710824.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_avocado_2710824 +subject: + type: ingredient + id: avocado +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2710824' + url: https://fdc.nal.usda.gov/food-details/2710824/nutrients + title: Avocado, Hass, peeled, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2710824 + data_type: Foundation + description: Avocado, Hass, peeled, raw +nutrition_per_100g: + calcium_mg: 14.5 + carbohydrate_g: 8.32 + energy_kcal: 206 + iron_mg: 0.613 + potassium_mg: 576 + protein_g: 1.81 + sodium_mg: 0.0 + total_fat_g: 20.3 diff --git a/culinary/source_mappings/usda_fdc_bacon_168277.yaml b/culinary/source_mappings/usda_fdc_bacon_168277.yaml new file mode 100644 index 0000000..235dcb3 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_bacon_168277.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_bacon_168277 +subject: + type: ingredient + id: bacon +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168277' + url: https://fdc.nal.usda.gov/food-details/168277/nutrients + title: Pork, cured, bacon, unprepared + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168277 + data_type: SR Legacy + description: Pork, cured, bacon, unprepared +nutrition_per_100g: + calcium_mg: 6.0 + carbohydrate_g: 0.0 + cholesterol_mg: 66.0 + dietary_fiber_g: 0.0 + energy_kcal: 393.0 + iron_mg: 0.38 + potassium_mg: 201.0 + protein_g: 13.66 + saturated_fat_g: 12.615 + sodium_mg: 751.0 + total_fat_g: 37.13 + total_sugars_g: 0.35 + vitamin_d_mcg: 0.4 diff --git a/culinary/source_mappings/usda_fdc_baking_powder_172803.yaml b/culinary/source_mappings/usda_fdc_baking_powder_172803.yaml new file mode 100644 index 0000000..7cbbefa --- /dev/null +++ b/culinary/source_mappings/usda_fdc_baking_powder_172803.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_baking_powder_172803 +subject: + type: ingredient + id: baking_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172803' + url: https://fdc.nal.usda.gov/food-details/172803/nutrients + title: Leavening agents, baking powder, double-acting, sodium aluminum sulfate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172803 + data_type: SR Legacy + description: Leavening agents, baking powder, double-acting, sodium aluminum sulfate +nutrition_per_100g: + calcium_mg: 5880.0 + carbohydrate_g: 27.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.2 + energy_kcal: 53.0 + iron_mg: 11.0 + potassium_mg: 20.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 10600.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_baking_soda_175040.yaml b/culinary/source_mappings/usda_fdc_baking_soda_175040.yaml new file mode 100644 index 0000000..45a853a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_baking_soda_175040.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_baking_soda_175040 +subject: + type: ingredient + id: baking_soda +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '175040' + url: https://fdc.nal.usda.gov/food-details/175040/nutrients + title: Leavening agents, baking soda + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 175040 + data_type: SR Legacy + description: Leavening agents, baking soda +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 0.0 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 27400.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_banana_1105314.yaml b/culinary/source_mappings/usda_fdc_banana_1105314.yaml new file mode 100644 index 0000000..fb8b12f --- /dev/null +++ b/culinary/source_mappings/usda_fdc_banana_1105314.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_banana_1105314 +subject: + type: ingredient + id: banana +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1105314' + url: https://fdc.nal.usda.gov/food-details/1105314/nutrients + title: Bananas, ripe and slightly ripe, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1105314 + data_type: Foundation + description: Bananas, ripe and slightly ripe, raw +nutrition_per_100g: + calcium_mg: 5.0 + carbohydrate_g: 23.0 + dietary_fiber_g: 1.7 + energy_kcal: 97.0 + iron_mg: 0.0 + potassium_mg: 326 + protein_g: 0.74 + sodium_mg: 0.0 + total_fat_g: 0.29 diff --git a/culinary/source_mappings/usda_fdc_barley_malt_powder_2027592.yaml b/culinary/source_mappings/usda_fdc_barley_malt_powder_2027592.yaml new file mode 100644 index 0000000..51ceeb4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_barley_malt_powder_2027592.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_barley_malt_powder_2027592 +subject: + type: ingredient + id: barley_malt_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2027592' + url: https://fdc.nal.usda.gov/food-details/2027592/nutrients + title: BARLEY MALT POWDER + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2027592 + data_type: Branded + description: BARLEY MALT POWDER + brand_owner: Glorybee Honey & Supplies + gtin_upc: '030042501043' +nutrition_per_100g: + carbohydrate_g: 100.0 + energy_kcal: 400.0 + potassium_mg: 750.0 + total_fat_g: 0.0 + total_sugars_g: 100.0 diff --git a/culinary/source_mappings/usda_fdc_barley_malt_syrup_169660.yaml b/culinary/source_mappings/usda_fdc_barley_malt_syrup_169660.yaml new file mode 100644 index 0000000..c2a7dc9 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_barley_malt_syrup_169660.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_barley_malt_syrup_169660 +subject: + type: ingredient + id: barley_malt_syrup +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169660' + url: https://fdc.nal.usda.gov/food-details/169660/nutrients + title: Syrups, malt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169660 + data_type: SR Legacy + description: Syrups, malt +nutrition_per_100g: + calcium_mg: 61.0 + carbohydrate_g: 71.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 318 + iron_mg: 0.96 + potassium_mg: 320 + protein_g: 6.2 + saturated_fat_g: 0.0 + sodium_mg: 35.0 + total_fat_g: 0.0 + total_sugars_g: 71.3 diff --git a/culinary/source_mappings/usda_fdc_basil_171317.yaml b/culinary/source_mappings/usda_fdc_basil_171317.yaml new file mode 100644 index 0000000..b7b21c8 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_basil_171317.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_basil_171317 +subject: + type: ingredient + id: basil +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171317' + url: https://fdc.nal.usda.gov/food-details/171317/nutrients + title: Spices, basil, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171317 + data_type: SR Legacy + description: Spices, basil, dried +nutrition_per_100g: + calcium_mg: 2240.0 + carbohydrate_g: 47.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 37.7 + energy_kcal: 233 + iron_mg: 89.8 + potassium_mg: 2630.0 + protein_g: 23.0 + saturated_fat_g: 2.16 + sodium_mg: 76.0 + total_fat_g: 4.07 + total_sugars_g: 1.71 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_bbq_sauce_hickory_smoke_2020420.yaml b/culinary/source_mappings/usda_fdc_bbq_sauce_hickory_smoke_2020420.yaml new file mode 100644 index 0000000..a6c3876 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_bbq_sauce_hickory_smoke_2020420.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_bbq_sauce_hickory_smoke_2020420 +subject: + type: ingredient + id: bbq_sauce_hickory_smoke +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2020420' + url: https://fdc.nal.usda.gov/food-details/2020420/nutrients + title: SWEET BABY RAY'S, HICKORY & BROWN SUGAR BARBECUE SAUCE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2020420 + data_type: Branded + description: SWEET BABY RAY'S, HICKORY & BROWN SUGAR BARBECUE SAUCE + brand_owner: Sweet Baby Rays Inc. + gtin_upc: 013409234228 +nutrition_per_100g: + carbohydrate_g: 48.65 + energy_kcal: 189.0 + iron_mg: 0.97 + protein_g: 0.0 + sodium_mg: 784.0 + total_fat_g: 0.0 + total_sugars_g: 43.24 diff --git a/culinary/source_mappings/usda_fdc_beef_base_2422131.yaml b/culinary/source_mappings/usda_fdc_beef_base_2422131.yaml new file mode 100644 index 0000000..8d32138 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_beef_base_2422131.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: usda_fdc_beef_base_2422131 +subject: + type: ingredient + id: beef_base +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2422131' + url: https://fdc.nal.usda.gov/food-details/2422131/nutrients + title: BEEF BASE, BEEF + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2422131 + data_type: Branded + description: BEEF BASE, BEEF + brand_owner: Sam's Club West + gtin_upc: '193968052812' +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 16.67 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 250.0 + iron_mg: 0.0 + potassium_mg: 1167.0 + protein_g: 16.67 + saturated_fat_g: 0.0 + sodium_mg: 9667.0 + total_fat_g: 16.67 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_beer_168746.yaml b/culinary/source_mappings/usda_fdc_beer_168746.yaml new file mode 100644 index 0000000..35c9e70 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_beer_168746.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_beer_168746 +subject: + type: ingredient + id: beer +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168746' + url: https://fdc.nal.usda.gov/food-details/168746/nutrients + title: Alcoholic beverage, beer, regular, all + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168746 + data_type: SR Legacy + description: Alcoholic beverage, beer, regular, all +nutrition_per_100g: + calcium_mg: 4.0 + carbohydrate_g: 3.55 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 43.0 + iron_mg: 0.02 + potassium_mg: 27.0 + protein_g: 0.46 + saturated_fat_g: 0.0 + sodium_mg: 4.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_black_pepper_ground_170931.yaml b/culinary/source_mappings/usda_fdc_black_pepper_ground_170931.yaml new file mode 100644 index 0000000..0529948 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_black_pepper_ground_170931.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_black_pepper_ground_170931 +subject: + type: ingredient + id: black_pepper_ground +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170931' + url: https://fdc.nal.usda.gov/food-details/170931/nutrients + title: Spices, pepper, black + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170931 + data_type: SR Legacy + description: Spices, pepper, black +nutrition_per_100g: + calcium_mg: 443 + carbohydrate_g: 64.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 25.3 + energy_kcal: 251 + iron_mg: 9.71 + potassium_mg: 1330.0 + protein_g: 10.4 + saturated_fat_g: 1.39 + sodium_mg: 20.0 + total_fat_g: 3.26 + total_sugars_g: 0.64 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_blueberry_2346411.yaml b/culinary/source_mappings/usda_fdc_blueberry_2346411.yaml new file mode 100644 index 0000000..f111896 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_blueberry_2346411.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_blueberry_2346411 +subject: + type: ingredient + id: blueberry +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346411' + url: https://fdc.nal.usda.gov/food-details/2346411/nutrients + title: Blueberries, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346411 + data_type: Foundation + description: Blueberries, raw +nutrition_per_100g: + calcium_mg: 11.69 + carbohydrate_g: 14.571775 + energy_kcal: 57.384621 + iron_mg: 0.3398 + potassium_mg: 85.64 + protein_g: 0.703125 + sodium_mg: 0.0 + total_fat_g: 0.3063 diff --git a/culinary/source_mappings/usda_fdc_bread_crumbs_174928.yaml b/culinary/source_mappings/usda_fdc_bread_crumbs_174928.yaml new file mode 100644 index 0000000..3f8d980 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_bread_crumbs_174928.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_bread_crumbs_174928 +subject: + type: ingredient + id: bread_crumbs +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174928' + url: https://fdc.nal.usda.gov/food-details/174928/nutrients + title: Bread, crumbs, dry, grated, plain + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174928 + data_type: SR Legacy + description: Bread, crumbs, dry, grated, plain +nutrition_per_100g: + calcium_mg: 183 + carbohydrate_g: 72.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 4.5 + energy_kcal: 395 + iron_mg: 4.83 + potassium_mg: 196 + protein_g: 13.4 + saturated_fat_g: 1.2 + sodium_mg: 732 + total_fat_g: 5.3 + total_sugars_g: 6.2 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_brown_sugar_168833.yaml b/culinary/source_mappings/usda_fdc_brown_sugar_168833.yaml new file mode 100644 index 0000000..e94a298 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_brown_sugar_168833.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_brown_sugar_168833 +subject: + type: ingredient + id: brown_sugar +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168833' + url: https://fdc.nal.usda.gov/food-details/168833/nutrients + title: Sugars, brown + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168833 + data_type: SR Legacy + description: Sugars, brown +nutrition_per_100g: + calcium_mg: 83.0 + carbohydrate_g: 98.1 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 380 + iron_mg: 0.71 + potassium_mg: 133 + protein_g: 0.12 + saturated_fat_g: 0.0 + sodium_mg: 28.0 + total_fat_g: 0.0 + total_sugars_g: 97.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_butter_789828.yaml b/culinary/source_mappings/usda_fdc_butter_789828.yaml new file mode 100644 index 0000000..8fa4336 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_butter_789828.yaml @@ -0,0 +1,27 @@ +schema_version: 2 +id: usda_fdc_butter_789828 +subject: + type: ingredient + id: butter +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '789828' + url: https://fdc.nal.usda.gov/food-details/789828/nutrients + title: Butter, stick, unsalted + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 789828 + data_type: Foundation + description: Butter, stick, unsalted +nutrition_per_100g: + calcium_mg: 14.0 + cholesterol_mg: 234 + iron_mg: 0.03 + potassium_mg: 19.0 + sodium_mg: 10.0 + total_fat_g: 81.5 diff --git a/culinary/source_mappings/usda_fdc_butter_flavored_shortening_2756254.yaml b/culinary/source_mappings/usda_fdc_butter_flavored_shortening_2756254.yaml new file mode 100644 index 0000000..85ca662 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_butter_flavored_shortening_2756254.yaml @@ -0,0 +1,25 @@ +schema_version: 2 +id: usda_fdc_butter_flavored_shortening_2756254 +subject: + type: ingredient + id: butter_flavored_shortening +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2756254' + url: https://fdc.nal.usda.gov/food-details/2756254/nutrients + title: Crisco Shortening, All Vegetable, Butter Flavor + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2756254 + data_type: Branded + description: Crisco Shortening, All Vegetable, Butter Flavor + gtin_upc: 00196005242412 +nutrition_per_100g: + energy_kcal: 733.3333 + saturated_fat_g: 23.3333 + total_fat_g: 80.0 diff --git a/culinary/source_mappings/usda_fdc_buttermilk_2259792.yaml b/culinary/source_mappings/usda_fdc_buttermilk_2259792.yaml new file mode 100644 index 0000000..b55aee5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_buttermilk_2259792.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_buttermilk_2259792 +subject: + type: ingredient + id: buttermilk +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2259792' + url: https://fdc.nal.usda.gov/food-details/2259792/nutrients + title: Buttermilk, low fat + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2259792 + data_type: Foundation + description: Buttermilk, low fat +nutrition_per_100g: + calcium_mg: 120 + carbohydrate_g: 4.81 + cholesterol_mg: 4.79 + energy_kcal: 42.9 + iron_mg: 0.013 + potassium_mg: 158 + protein_g: 3.46 + saturated_fat_g: 0.552 + sodium_mg: 92.5 + total_fat_g: 1.08 + vitamin_d_mcg: 0.543 diff --git a/culinary/source_mappings/usda_fdc_buttermilk_powder_171274.yaml b/culinary/source_mappings/usda_fdc_buttermilk_powder_171274.yaml new file mode 100644 index 0000000..6dea431 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_buttermilk_powder_171274.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_buttermilk_powder_171274 +subject: + type: ingredient + id: buttermilk_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171274' + url: https://fdc.nal.usda.gov/food-details/171274/nutrients + title: Milk, buttermilk, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171274 + data_type: SR Legacy + description: Milk, buttermilk, dried +nutrition_per_100g: + calcium_mg: 1180.0 + carbohydrate_g: 49.0 + cholesterol_mg: 69.0 + dietary_fiber_g: 0.0 + energy_kcal: 387 + iron_mg: 0.3 + potassium_mg: 1590.0 + protein_g: 34.3 + saturated_fat_g: 3.6 + sodium_mg: 517 + total_fat_g: 5.78 + total_sugars_g: 49.0 + vitamin_d_mcg: 0.5 diff --git a/culinary/source_mappings/usda_fdc_canola_oil_748278.yaml b/culinary/source_mappings/usda_fdc_canola_oil_748278.yaml new file mode 100644 index 0000000..9628073 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_canola_oil_748278.yaml @@ -0,0 +1,22 @@ +schema_version: 2 +id: usda_fdc_canola_oil_748278 +subject: + type: ingredient + id: canola_oil +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '748278' + url: https://fdc.nal.usda.gov/food-details/748278/nutrients + title: Oil, canola + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 748278 + data_type: Foundation + description: Oil, canola +nutrition_per_100g: + saturated_fat_g: 6.61 diff --git a/culinary/source_mappings/usda_fdc_cardamom_170919.yaml b/culinary/source_mappings/usda_fdc_cardamom_170919.yaml new file mode 100644 index 0000000..db85157 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cardamom_170919.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_cardamom_170919 +subject: + type: ingredient + id: cardamom +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170919' + url: https://fdc.nal.usda.gov/food-details/170919/nutrients + title: Spices, cardamom + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170919 + data_type: SR Legacy + description: Spices, cardamom +nutrition_per_100g: + calcium_mg: 383 + carbohydrate_g: 68.5 + cholesterol_mg: 0.0 + dietary_fiber_g: 28.0 + energy_kcal: 311 + iron_mg: 14.0 + potassium_mg: 1120.0 + protein_g: 10.8 + saturated_fat_g: 0.68 + sodium_mg: 18.0 + total_fat_g: 6.7 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_carrot_2258586.yaml b/culinary/source_mappings/usda_fdc_carrot_2258586.yaml new file mode 100644 index 0000000..081bc16 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_carrot_2258586.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_carrot_2258586 +subject: + type: ingredient + id: carrot +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2258586' + url: https://fdc.nal.usda.gov/food-details/2258586/nutrients + title: Carrots, mature, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2258586 + data_type: Foundation + description: Carrots, mature, raw +nutrition_per_100g: + calcium_mg: 30.5 + carbohydrate_g: 10.3 + dietary_fiber_g: 3.1 + energy_kcal: 45.0 + iron_mg: 0.15 + potassium_mg: 280 + protein_g: 0.941 + sodium_mg: 86.6 + total_fat_g: 0.351 diff --git a/culinary/source_mappings/usda_fdc_cayenne_170932.yaml b/culinary/source_mappings/usda_fdc_cayenne_170932.yaml new file mode 100644 index 0000000..0b38f43 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cayenne_170932.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cayenne_170932 +subject: + type: ingredient + id: cayenne +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170932' + url: https://fdc.nal.usda.gov/food-details/170932/nutrients + title: Spices, pepper, red or cayenne + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170932 + data_type: SR Legacy + description: Spices, pepper, red or cayenne +nutrition_per_100g: + calcium_mg: 148 + carbohydrate_g: 56.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 27.2 + energy_kcal: 318 + iron_mg: 7.8 + potassium_mg: 2010.0 + protein_g: 12.0 + saturated_fat_g: 3.26 + sodium_mg: 30.0 + total_fat_g: 17.3 + total_sugars_g: 10.3 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cheddar_cheese_328637.yaml b/culinary/source_mappings/usda_fdc_cheddar_cheese_328637.yaml new file mode 100644 index 0000000..328531b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cheddar_cheese_328637.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_cheddar_cheese_328637 +subject: + type: ingredient + id: cheddar_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '328637' + url: https://fdc.nal.usda.gov/food-details/328637/nutrients + title: Cheese, cheddar + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 328637 + data_type: Foundation + description: Cheese, cheddar +nutrition_per_100g: + calcium_mg: 707 + carbohydrate_g: 2.44 + cholesterol_mg: 100 + energy_kcal: 408 + iron_mg: 0.16 + potassium_mg: 77.0 + protein_g: 23.3 + saturated_fat_g: 19.2 + sodium_mg: 654 + total_fat_g: 34.0 diff --git a/culinary/source_mappings/usda_fdc_chicken_base_1948045.yaml b/culinary/source_mappings/usda_fdc_chicken_base_1948045.yaml new file mode 100644 index 0000000..2ece09e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chicken_base_1948045.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_chicken_base_1948045 +subject: + type: ingredient + id: chicken_base +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1948045' + url: https://fdc.nal.usda.gov/food-details/1948045/nutrients + title: CHICKEN BASE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1948045 + data_type: Branded + description: CHICKEN BASE + brand_owner: Wal-Mart Stores, Inc. + gtin_upc: 078742244464 +nutrition_per_100g: + carbohydrate_g: 33.33 + cholesterol_mg: 83.0 + energy_kcal: 250.0 + protein_g: 0.0 + sodium_mg: 9667.0 + total_fat_g: 16.67 diff --git a/culinary/source_mappings/usda_fdc_chicken_breast_2646170.yaml b/culinary/source_mappings/usda_fdc_chicken_breast_2646170.yaml new file mode 100644 index 0000000..e75a42c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chicken_breast_2646170.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_chicken_breast_2646170 +subject: + type: ingredient + id: chicken_breast +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2646170' + url: https://fdc.nal.usda.gov/food-details/2646170/nutrients + title: Chicken, breast, boneless, skinless, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2646170 + data_type: Foundation + description: Chicken, breast, boneless, skinless, raw +nutrition_per_100g: + calcium_mg: 3.94 + carbohydrate_g: 0.0 + cholesterol_mg: 72.7 + energy_kcal: 112 + iron_mg: 0.354 + potassium_mg: 330 + protein_g: 22.5 + saturated_fat_g: 0.349 + sodium_mg: 65.8 + total_fat_g: 1.93 diff --git a/culinary/source_mappings/usda_fdc_chili_powder_171319.yaml b/culinary/source_mappings/usda_fdc_chili_powder_171319.yaml new file mode 100644 index 0000000..7c49fa5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chili_powder_171319.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_chili_powder_171319 +subject: + type: ingredient + id: chili_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171319' + url: https://fdc.nal.usda.gov/food-details/171319/nutrients + title: Spices, chili powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171319 + data_type: SR Legacy + description: Spices, chili powder +nutrition_per_100g: + calcium_mg: 330 + carbohydrate_g: 49.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 34.8 + energy_kcal: 282 + iron_mg: 17.3 + potassium_mg: 1950.0 + protein_g: 13.5 + saturated_fat_g: 2.46 + sodium_mg: 2870.0 + total_fat_g: 14.3 + total_sugars_g: 7.19 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_chipotle_pepper_adobo_2420526.yaml b/culinary/source_mappings/usda_fdc_chipotle_pepper_adobo_2420526.yaml new file mode 100644 index 0000000..86098d5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chipotle_pepper_adobo_2420526.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: usda_fdc_chipotle_pepper_adobo_2420526 +subject: + type: ingredient + id: chipotle_pepper_adobo +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2420526' + url: https://fdc.nal.usda.gov/food-details/2420526/nutrients + title: CHIPOTLES PEPPERS IN ADOBO SAUCE, CHIPOTLES PEPPERS IN ADOBO + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2420526 + data_type: Branded + description: CHIPOTLES PEPPERS IN ADOBO SAUCE, CHIPOTLES PEPPERS IN ADOBO + brand_owner: Conservas La Costena S.A. + gtin_upc: 076397030180 +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 13.33 + cholesterol_mg: 0.0 + dietary_fiber_g: 3.3 + energy_kcal: 67.0 + iron_mg: 2.4 + potassium_mg: 467.0 + protein_g: 3.33 + saturated_fat_g: 0.0 + sodium_mg: 800.0 + total_fat_g: 0.0 + total_sugars_g: 6.67 diff --git a/culinary/source_mappings/usda_fdc_chipotle_pepper_sauce_tobasco_174528.yaml b/culinary/source_mappings/usda_fdc_chipotle_pepper_sauce_tobasco_174528.yaml new file mode 100644 index 0000000..75effd8 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chipotle_pepper_sauce_tobasco_174528.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_chipotle_pepper_sauce_tobasco_174528 +subject: + type: ingredient + id: chipotle_pepper_sauce_tobasco +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174528' + url: https://fdc.nal.usda.gov/food-details/174528/nutrients + title: Sauce, ready-to-serve, pepper, TABASCO + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174528 + data_type: SR Legacy + description: Sauce, ready-to-serve, pepper, TABASCO +nutrition_per_100g: + calcium_mg: 12.0 + carbohydrate_g: 0.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.6 + energy_kcal: 12.0 + iron_mg: 1.16 + potassium_mg: 128 + protein_g: 1.29 + saturated_fat_g: 0.106 + sodium_mg: 633 + total_fat_g: 0.76 + total_sugars_g: 0.13 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_chipotle_powder_2545016.yaml b/culinary/source_mappings/usda_fdc_chipotle_powder_2545016.yaml new file mode 100644 index 0000000..26dd7d6 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_chipotle_powder_2545016.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_chipotle_powder_2545016 +subject: + type: ingredient + id: chipotle_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2545016' + url: https://fdc.nal.usda.gov/food-details/2545016/nutrients + title: GROUND CHIPOTLE CHILE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2545016 + data_type: Branded + description: GROUND CHIPOTLE CHILE + brand_owner: 'B&G Foods North America, Inc. ' + gtin_upc: '017324003075' +nutrition_per_100g: + carbohydrate_g: 0.0 + energy_kcal: 625.0 + protein_g: 0.0 + sodium_mg: 0.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cilantro_169997.yaml b/culinary/source_mappings/usda_fdc_cilantro_169997.yaml new file mode 100644 index 0000000..9526376 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cilantro_169997.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cilantro_169997 +subject: + type: ingredient + id: cilantro +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169997' + url: https://fdc.nal.usda.gov/food-details/169997/nutrients + title: Coriander (cilantro) leaves, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169997 + data_type: SR Legacy + description: Coriander (cilantro) leaves, raw +nutrition_per_100g: + calcium_mg: 67.0 + carbohydrate_g: 3.67 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.8 + energy_kcal: 23.0 + iron_mg: 1.77 + potassium_mg: 521 + protein_g: 2.13 + saturated_fat_g: 0.014 + sodium_mg: 46.0 + total_fat_g: 0.52 + total_sugars_g: 0.87 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cinnamon_171320.yaml b/culinary/source_mappings/usda_fdc_cinnamon_171320.yaml new file mode 100644 index 0000000..c3325ad --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cinnamon_171320.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cinnamon_171320 +subject: + type: ingredient + id: cinnamon +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171320' + url: https://fdc.nal.usda.gov/food-details/171320/nutrients + title: Spices, cinnamon, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171320 + data_type: SR Legacy + description: Spices, cinnamon, ground +nutrition_per_100g: + calcium_mg: 1000.0 + carbohydrate_g: 80.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 53.1 + energy_kcal: 247 + iron_mg: 8.32 + potassium_mg: 431 + protein_g: 3.99 + saturated_fat_g: 0.345 + sodium_mg: 10.0 + total_fat_g: 1.24 + total_sugars_g: 2.17 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cloves_171321.yaml b/culinary/source_mappings/usda_fdc_cloves_171321.yaml new file mode 100644 index 0000000..a2d86bc --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cloves_171321.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cloves_171321 +subject: + type: ingredient + id: cloves +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171321' + url: https://fdc.nal.usda.gov/food-details/171321/nutrients + title: Spices, cloves, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171321 + data_type: SR Legacy + description: Spices, cloves, ground +nutrition_per_100g: + calcium_mg: 632 + carbohydrate_g: 65.5 + cholesterol_mg: 0.0 + dietary_fiber_g: 33.9 + energy_kcal: 274 + iron_mg: 11.8 + potassium_mg: 1020.0 + protein_g: 5.97 + saturated_fat_g: 3.95 + sodium_mg: 277 + total_fat_g: 13.0 + total_sugars_g: 2.38 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cocoa_powder_169593.yaml b/culinary/source_mappings/usda_fdc_cocoa_powder_169593.yaml new file mode 100644 index 0000000..29a347c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cocoa_powder_169593.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cocoa_powder_169593 +subject: + type: ingredient + id: cocoa_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169593' + url: https://fdc.nal.usda.gov/food-details/169593/nutrients + title: Cocoa, dry powder, unsweetened + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169593 + data_type: SR Legacy + description: Cocoa, dry powder, unsweetened +nutrition_per_100g: + calcium_mg: 128 + carbohydrate_g: 57.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 37.0 + energy_kcal: 228 + iron_mg: 13.9 + potassium_mg: 1520.0 + protein_g: 19.6 + saturated_fat_g: 8.07 + sodium_mg: 21.0 + total_fat_g: 13.7 + total_sugars_g: 1.75 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_coconut_milk_170173.yaml b/culinary/source_mappings/usda_fdc_coconut_milk_170173.yaml new file mode 100644 index 0000000..a8b7e0b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_coconut_milk_170173.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_coconut_milk_170173 +subject: + type: ingredient + id: coconut_milk +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170173' + url: https://fdc.nal.usda.gov/food-details/170173/nutrients + title: Nuts, coconut milk, canned (liquid expressed from grated meat and water) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170173 + data_type: SR Legacy + description: Nuts, coconut milk, canned (liquid expressed from grated meat and water) +nutrition_per_100g: + calcium_mg: 18.0 + carbohydrate_g: 2.81 + cholesterol_mg: 0.0 + energy_kcal: 197 + iron_mg: 3.3 + potassium_mg: 220 + protein_g: 2.02 + saturated_fat_g: 18.9 + sodium_mg: 13.0 + total_fat_g: 21.3 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_confectioners_sugar_169656.yaml b/culinary/source_mappings/usda_fdc_confectioners_sugar_169656.yaml new file mode 100644 index 0000000..76bdca6 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_confectioners_sugar_169656.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_confectioners_sugar_169656 +subject: + type: ingredient + id: confectioners_sugar +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169656' + url: https://fdc.nal.usda.gov/food-details/169656/nutrients + title: Sugars, powdered + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169656 + data_type: SR Legacy + description: Sugars, powdered +nutrition_per_100g: + calcium_mg: 1.0 + carbohydrate_g: 99.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 389 + iron_mg: 0.06 + potassium_mg: 2.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 2.0 + total_fat_g: 0.0 + total_sugars_g: 97.8 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cooked_pinto_beans_drained_175200.yaml b/culinary/source_mappings/usda_fdc_cooked_pinto_beans_drained_175200.yaml new file mode 100644 index 0000000..7b6e2e5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cooked_pinto_beans_drained_175200.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cooked_pinto_beans_drained_175200 +subject: + type: ingredient + id: cooked_pinto_beans_drained +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '175200' + url: https://fdc.nal.usda.gov/food-details/175200/nutrients + title: Beans, pinto, mature seeds, cooked, boiled, without salt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 175200 + data_type: SR Legacy + description: Beans, pinto, mature seeds, cooked, boiled, without salt +nutrition_per_100g: + calcium_mg: 46.0 + carbohydrate_g: 26.2 + cholesterol_mg: 0.0 + dietary_fiber_g: 9.0 + energy_kcal: 143 + iron_mg: 2.09 + potassium_mg: 436 + protein_g: 9.01 + saturated_fat_g: 0.136 + sodium_mg: 1.0 + total_fat_g: 0.65 + total_sugars_g: 0.34 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_coriander_170922.yaml b/culinary/source_mappings/usda_fdc_coriander_170922.yaml new file mode 100644 index 0000000..0572b97 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_coriander_170922.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_coriander_170922 +subject: + type: ingredient + id: coriander +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170922' + url: https://fdc.nal.usda.gov/food-details/170922/nutrients + title: Spices, coriander seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170922 + data_type: SR Legacy + description: Spices, coriander seed +nutrition_per_100g: + calcium_mg: 709 + carbohydrate_g: 55.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 41.9 + energy_kcal: 298 + iron_mg: 16.3 + potassium_mg: 1270.0 + protein_g: 12.4 + saturated_fat_g: 0.99 + sodium_mg: 35.0 + total_fat_g: 17.8 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_corn_syrup_light_168837.yaml b/culinary/source_mappings/usda_fdc_corn_syrup_light_168837.yaml new file mode 100644 index 0000000..9212f4f --- /dev/null +++ b/culinary/source_mappings/usda_fdc_corn_syrup_light_168837.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_corn_syrup_light_168837 +subject: + type: ingredient + id: corn_syrup_light +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168837' + url: https://fdc.nal.usda.gov/food-details/168837/nutrients + title: Syrups, corn, light + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168837 + data_type: SR Legacy + description: Syrups, corn, light +nutrition_per_100g: + calcium_mg: 13.0 + carbohydrate_g: 76.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 283 + iron_mg: 0.0 + potassium_mg: 1.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 62.0 + total_fat_g: 0.2 + total_sugars_g: 76.8 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cornstarch_169698.yaml b/culinary/source_mappings/usda_fdc_cornstarch_169698.yaml new file mode 100644 index 0000000..69556ec --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cornstarch_169698.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cornstarch_169698 +subject: + type: ingredient + id: cornstarch +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169698' + url: https://fdc.nal.usda.gov/food-details/169698/nutrients + title: Cornstarch + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169698 + data_type: SR Legacy + description: Cornstarch +nutrition_per_100g: + calcium_mg: 2.0 + carbohydrate_g: 91.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.9 + energy_kcal: 381 + iron_mg: 0.47 + potassium_mg: 3.0 + protein_g: 0.26 + saturated_fat_g: 0.009 + sodium_mg: 9.0 + total_fat_g: 0.05 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_cream_cheese_2346385.yaml b/culinary/source_mappings/usda_fdc_cream_cheese_2346385.yaml new file mode 100644 index 0000000..77b12d7 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cream_cheese_2346385.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_cream_cheese_2346385 +subject: + type: ingredient + id: cream_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346385' + url: https://fdc.nal.usda.gov/food-details/2346385/nutrients + title: Cream cheese, full fat, block + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346385 + data_type: Foundation + description: Cream cheese, full fat, block +nutrition_per_100g: + calcium_mg: 97.1 + carbohydrate_g: 4.56 + cholesterol_mg: 101 + energy_kcal: 337 + iron_mg: 0.0 + potassium_mg: 125 + protein_g: 5.79 + saturated_fat_g: 19.7 + sodium_mg: 368 + total_fat_g: 33.5 diff --git a/culinary/source_mappings/usda_fdc_cumin_170923.yaml b/culinary/source_mappings/usda_fdc_cumin_170923.yaml new file mode 100644 index 0000000..11d2df7 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_cumin_170923.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_cumin_170923 +subject: + type: ingredient + id: cumin +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170923' + url: https://fdc.nal.usda.gov/food-details/170923/nutrients + title: Spices, cumin seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170923 + data_type: SR Legacy + description: Spices, cumin seed +nutrition_per_100g: + calcium_mg: 931 + carbohydrate_g: 44.2 + cholesterol_mg: 0.0 + dietary_fiber_g: 10.5 + energy_kcal: 375 + iron_mg: 66.4 + potassium_mg: 1790.0 + protein_g: 17.8 + saturated_fat_g: 1.54 + sodium_mg: 168 + total_fat_g: 22.3 + total_sugars_g: 2.25 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_dark_chocolate_170273.yaml b/culinary/source_mappings/usda_fdc_dark_chocolate_170273.yaml new file mode 100644 index 0000000..e8941ca --- /dev/null +++ b/culinary/source_mappings/usda_fdc_dark_chocolate_170273.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_dark_chocolate_170273 +subject: + type: ingredient + id: dark_chocolate +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170273' + url: https://fdc.nal.usda.gov/food-details/170273/nutrients + title: Chocolate, dark, 70-85% cacao solids + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170273 + data_type: SR Legacy + description: Chocolate, dark, 70-85% cacao solids +nutrition_per_100g: + calcium_mg: 73.0 + carbohydrate_g: 45.9 + cholesterol_mg: 3.0 + dietary_fiber_g: 10.9 + energy_kcal: 598 + iron_mg: 11.9 + potassium_mg: 715 + protein_g: 7.79 + saturated_fat_g: 24.5 + sodium_mg: 20.0 + total_fat_g: 42.6 + total_sugars_g: 24.0 diff --git a/culinary/source_mappings/usda_fdc_dark_cocoa_powder_169594.yaml b/culinary/source_mappings/usda_fdc_dark_cocoa_powder_169594.yaml new file mode 100644 index 0000000..a1444fe --- /dev/null +++ b/culinary/source_mappings/usda_fdc_dark_cocoa_powder_169594.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_dark_cocoa_powder_169594 +subject: + type: ingredient + id: dark_cocoa_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169594' + url: https://fdc.nal.usda.gov/food-details/169594/nutrients + title: Cocoa, dry powder, unsweetened, processed with alkali + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169594 + data_type: SR Legacy + description: Cocoa, dry powder, unsweetened, processed with alkali +nutrition_per_100g: + calcium_mg: 111 + carbohydrate_g: 58.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 29.8 + energy_kcal: 220 + iron_mg: 15.5 + potassium_mg: 2510.0 + protein_g: 18.1 + saturated_fat_g: 7.76 + sodium_mg: 19.0 + total_fat_g: 13.1 + total_sugars_g: 1.76 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_dextrose_1991846.yaml b/culinary/source_mappings/usda_fdc_dextrose_1991846.yaml new file mode 100644 index 0000000..f798714 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_dextrose_1991846.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: usda_fdc_dextrose_1991846 +subject: + type: ingredient + id: dextrose +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1991846' + url: https://fdc.nal.usda.gov/food-details/1991846/nutrients + title: DEXTROSE PURE AND NATURAL SWEETENER, DEXTROSE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1991846 + data_type: Branded + description: DEXTROSE PURE AND NATURAL SWEETENER, DEXTROSE + brand_owner: Now Health Group Inc. + gtin_upc: '733739069252' +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 87.5 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 375.0 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 0.0 + total_fat_g: 0.0 + total_sugars_g: 87.5 diff --git a/culinary/source_mappings/usda_fdc_dill_172233.yaml b/culinary/source_mappings/usda_fdc_dill_172233.yaml new file mode 100644 index 0000000..23a777e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_dill_172233.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_dill_172233 +subject: + type: ingredient + id: dill +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172233' + url: https://fdc.nal.usda.gov/food-details/172233/nutrients + title: Dill weed, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172233 + data_type: SR Legacy + description: Dill weed, fresh +nutrition_per_100g: + calcium_mg: 208 + carbohydrate_g: 7.02 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.1 + energy_kcal: 43.0 + iron_mg: 6.59 + potassium_mg: 738 + protein_g: 3.46 + saturated_fat_g: 0.06 + sodium_mg: 61.0 + total_fat_g: 1.12 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_dried_chilis_168570.yaml b/culinary/source_mappings/usda_fdc_dried_chilis_168570.yaml new file mode 100644 index 0000000..973f985 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_dried_chilis_168570.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_dried_chilis_168570 +subject: + type: ingredient + id: dried_chilis +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168570' + url: https://fdc.nal.usda.gov/food-details/168570/nutrients + title: Peppers, hot chile, sun-dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168570 + data_type: SR Legacy + description: Peppers, hot chile, sun-dried +nutrition_per_100g: + calcium_mg: 45.0 + carbohydrate_g: 69.86 + cholesterol_mg: 0.0 + dietary_fiber_g: 28.7 + energy_kcal: 324.0 + iron_mg: 6.04 + potassium_mg: 1870.0 + protein_g: 10.58 + saturated_fat_g: 0.813 + sodium_mg: 91.0 + total_fat_g: 5.81 + total_sugars_g: 41.06 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_egg_whites_172183.yaml b/culinary/source_mappings/usda_fdc_egg_whites_172183.yaml new file mode 100644 index 0000000..93b1349 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_egg_whites_172183.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_egg_whites_172183 +subject: + type: ingredient + id: egg_whites +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172183' + url: https://fdc.nal.usda.gov/food-details/172183/nutrients + title: Egg, white, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172183 + data_type: SR Legacy + description: Egg, white, raw, fresh +nutrition_per_100g: + calcium_mg: 7.0 + carbohydrate_g: 0.73 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 52.0 + iron_mg: 0.08 + potassium_mg: 163 + protein_g: 10.9 + saturated_fat_g: 0.0 + sodium_mg: 166 + total_fat_g: 0.17 + total_sugars_g: 0.71 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_egg_whole_171287.yaml b/culinary/source_mappings/usda_fdc_egg_whole_171287.yaml new file mode 100644 index 0000000..e857833 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_egg_whole_171287.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_egg_whole_171287 +subject: + type: ingredient + id: egg_whole +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171287' + url: https://fdc.nal.usda.gov/food-details/171287/nutrients + title: Egg, whole, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171287 + data_type: SR Legacy + description: Egg, whole, raw, fresh +nutrition_per_100g: + calcium_mg: 56.0 + carbohydrate_g: 0.72 + cholesterol_mg: 372 + dietary_fiber_g: 0.0 + energy_kcal: 143 + iron_mg: 1.75 + potassium_mg: 138 + protein_g: 12.6 + saturated_fat_g: 3.13 + sodium_mg: 142 + total_fat_g: 9.51 + total_sugars_g: 0.37 + vitamin_d_mcg: 2.0 diff --git a/culinary/source_mappings/usda_fdc_egg_yolk_172184.yaml b/culinary/source_mappings/usda_fdc_egg_yolk_172184.yaml new file mode 100644 index 0000000..c22b8cf --- /dev/null +++ b/culinary/source_mappings/usda_fdc_egg_yolk_172184.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_egg_yolk_172184 +subject: + type: ingredient + id: egg_yolk +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172184' + url: https://fdc.nal.usda.gov/food-details/172184/nutrients + title: Egg, yolk, raw, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172184 + data_type: SR Legacy + description: Egg, yolk, raw, fresh +nutrition_per_100g: + calcium_mg: 129 + carbohydrate_g: 3.59 + cholesterol_mg: 1080.0 + dietary_fiber_g: 0.0 + energy_kcal: 322 + iron_mg: 2.73 + potassium_mg: 109 + protein_g: 15.9 + saturated_fat_g: 9.55 + sodium_mg: 48.0 + total_fat_g: 26.5 + total_sugars_g: 0.56 + vitamin_d_mcg: 5.4 diff --git a/culinary/source_mappings/usda_fdc_espresso_powder_2059824.yaml b/culinary/source_mappings/usda_fdc_espresso_powder_2059824.yaml new file mode 100644 index 0000000..30c5721 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_espresso_powder_2059824.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_espresso_powder_2059824 +subject: + type: ingredient + id: espresso_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2059824' + url: https://fdc.nal.usda.gov/food-details/2059824/nutrients + title: ESPRESSO INSTANT POWDER, ESPRESSO + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2059824 + data_type: Branded + description: ESPRESSO INSTANT POWDER, ESPRESSO + brand_owner: George DeLallo Co., Inc. + gtin_upc: 072368569901 +nutrition_per_100g: + carbohydrate_g: 100.0 + energy_kcal: 250.0 + protein_g: 0.0 + sodium_mg: 250.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_fennel_seed_171323.yaml b/culinary/source_mappings/usda_fdc_fennel_seed_171323.yaml new file mode 100644 index 0000000..8f398e4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_fennel_seed_171323.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_fennel_seed_171323 +subject: + type: ingredient + id: fennel_seed +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171323' + url: https://fdc.nal.usda.gov/food-details/171323/nutrients + title: Spices, fennel seed + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171323 + data_type: SR Legacy + description: Spices, fennel seed +nutrition_per_100g: + calcium_mg: 1200.0 + carbohydrate_g: 52.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 39.8 + energy_kcal: 345 + iron_mg: 18.5 + potassium_mg: 1690.0 + protein_g: 15.8 + saturated_fat_g: 0.48 + sodium_mg: 88.0 + total_fat_g: 14.9 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_flour_all_purpose_790018.yaml b/culinary/source_mappings/usda_fdc_flour_all_purpose_790018.yaml new file mode 100644 index 0000000..2e7d0b7 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_all_purpose_790018.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_flour_all_purpose_790018 +subject: + type: ingredient + id: flour_all_purpose +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '790018' + url: https://fdc.nal.usda.gov/food-details/790018/nutrients + title: Flour, wheat, all-purpose, unenriched, unbleached + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 790018 + data_type: Foundation + description: Flour, wheat, all-purpose, unenriched, unbleached +nutrition_per_100g: + calcium_mg: 22.0 + carbohydrate_g: 74.6 + dietary_fiber_g: 3.0 + energy_kcal: 362 + iron_mg: 1.18 + potassium_mg: 150 + protein_g: 12.0 + sodium_mg: 2.0 + total_fat_g: 1.7 diff --git a/culinary/source_mappings/usda_fdc_flour_bread_790146.yaml b/culinary/source_mappings/usda_fdc_flour_bread_790146.yaml new file mode 100644 index 0000000..512ae72 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_bread_790146.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_flour_bread_790146 +subject: + type: ingredient + id: flour_bread +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '790146' + url: https://fdc.nal.usda.gov/food-details/790146/nutrients + title: Flour, bread, white, enriched, unbleached + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 790146 + data_type: Foundation + description: Flour, bread, white, enriched, unbleached +nutrition_per_100g: + calcium_mg: 19.0 + carbohydrate_g: 72.8 + energy_kcal: 363 + iron_mg: 5.55 + potassium_mg: 127 + protein_g: 14.3 + sodium_mg: 3.0 + total_fat_g: 1.65 diff --git a/culinary/source_mappings/usda_fdc_flour_cake_169723.yaml b/culinary/source_mappings/usda_fdc_flour_cake_169723.yaml new file mode 100644 index 0000000..2fabc71 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_cake_169723.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_flour_cake_169723 +subject: + type: ingredient + id: flour_cake +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169723' + url: https://fdc.nal.usda.gov/food-details/169723/nutrients + title: Wheat flour, white, cake, enriched + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169723 + data_type: SR Legacy + description: Wheat flour, white, cake, enriched +nutrition_per_100g: + calcium_mg: 14.0 + carbohydrate_g: 78.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 1.7 + energy_kcal: 362 + iron_mg: 7.32 + potassium_mg: 105 + protein_g: 8.2 + saturated_fat_g: 0.127 + sodium_mg: 2.0 + total_fat_g: 0.86 + total_sugars_g: 0.31 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_flour_corn_2710835.yaml b/culinary/source_mappings/usda_fdc_flour_corn_2710835.yaml new file mode 100644 index 0000000..05f2947 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_corn_2710835.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_flour_corn_2710835 +subject: + type: ingredient + id: flour_corn +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2710835' + url: https://fdc.nal.usda.gov/food-details/2710835/nutrients + title: Corn flour, masa harina, white or yellow, dry, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2710835 + data_type: Foundation + description: Corn flour, masa harina, white or yellow, dry, raw +nutrition_per_100g: + calcium_mg: 112 + carbohydrate_g: 76.7 + dietary_fiber_g: 7.04 + energy_kcal: 366 + iron_mg: 1.7 + potassium_mg: 277 + protein_g: 7.56 + sodium_mg: 2.73 + total_fat_g: 4.34 diff --git a/culinary/source_mappings/usda_fdc_flour_pastry_1104913.yaml b/culinary/source_mappings/usda_fdc_flour_pastry_1104913.yaml new file mode 100644 index 0000000..43d91fa --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_pastry_1104913.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_flour_pastry_1104913 +subject: + type: ingredient + id: flour_pastry +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1104913' + url: https://fdc.nal.usda.gov/food-details/1104913/nutrients + title: Flour, pastry, unenriched, unbleached + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1104913 + data_type: Foundation + description: Flour, pastry, unenriched, unbleached +nutrition_per_100g: + calcium_mg: 17.0 + carbohydrate_g: 77.2 + energy_kcal: 358 + iron_mg: 0.87 + potassium_mg: 142 + protein_g: 8.75 + sodium_mg: 1.0 + total_fat_g: 1.64 diff --git a/culinary/source_mappings/usda_fdc_flour_whole_wheat_790085.yaml b/culinary/source_mappings/usda_fdc_flour_whole_wheat_790085.yaml new file mode 100644 index 0000000..5bf5e38 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_flour_whole_wheat_790085.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_flour_whole_wheat_790085 +subject: + type: ingredient + id: flour_whole_wheat +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '790085' + url: https://fdc.nal.usda.gov/food-details/790085/nutrients + title: Flour, whole wheat, unenriched + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 790085 + data_type: Foundation + description: Flour, whole wheat, unenriched +nutrition_per_100g: + calcium_mg: 38.0 + carbohydrate_g: 71.2 + dietary_fiber_g: 10.6 + energy_kcal: 370 + iron_mg: 3.86 + potassium_mg: 376 + protein_g: 15.1 + sodium_mg: 3.0 + total_fat_g: 2.73 diff --git a/culinary/source_mappings/usda_fdc_garlic_1104647.yaml b/culinary/source_mappings/usda_fdc_garlic_1104647.yaml new file mode 100644 index 0000000..e26ab5a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_garlic_1104647.yaml @@ -0,0 +1,26 @@ +schema_version: 2 +id: usda_fdc_garlic_1104647 +subject: + type: ingredient + id: garlic +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1104647' + url: https://fdc.nal.usda.gov/food-details/1104647/nutrients + title: Garlic, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1104647 + data_type: Foundation + description: Garlic, raw +nutrition_per_100g: + carbohydrate_g: 28.2 + dietary_fiber_g: 2.7 + energy_kcal: 143 + protein_g: 6.62 + total_fat_g: 0.38 diff --git a/culinary/source_mappings/usda_fdc_garlic_powder_171325.yaml b/culinary/source_mappings/usda_fdc_garlic_powder_171325.yaml new file mode 100644 index 0000000..238d0d8 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_garlic_powder_171325.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_garlic_powder_171325 +subject: + type: ingredient + id: garlic_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171325' + url: https://fdc.nal.usda.gov/food-details/171325/nutrients + title: Spices, garlic powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171325 + data_type: SR Legacy + description: Spices, garlic powder +nutrition_per_100g: + calcium_mg: 79.0 + carbohydrate_g: 72.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 9.0 + energy_kcal: 331 + iron_mg: 5.65 + potassium_mg: 1190.0 + protein_g: 16.6 + saturated_fat_g: 0.249 + sodium_mg: 60.0 + total_fat_g: 0.73 + total_sugars_g: 2.43 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_gelatin_169599.yaml b/culinary/source_mappings/usda_fdc_gelatin_169599.yaml new file mode 100644 index 0000000..838fc4d --- /dev/null +++ b/culinary/source_mappings/usda_fdc_gelatin_169599.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_gelatin_169599 +subject: + type: ingredient + id: gelatin +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169599' + url: https://fdc.nal.usda.gov/food-details/169599/nutrients + title: Gelatins, dry powder, unsweetened + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169599 + data_type: SR Legacy + description: Gelatins, dry powder, unsweetened +nutrition_per_100g: + calcium_mg: 55.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 335 + iron_mg: 1.11 + potassium_mg: 16.0 + protein_g: 85.6 + saturated_fat_g: 0.07 + sodium_mg: 196 + total_fat_g: 0.1 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_ginger_169231.yaml b/culinary/source_mappings/usda_fdc_ginger_169231.yaml new file mode 100644 index 0000000..f6625d9 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_ginger_169231.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_ginger_169231 +subject: + type: ingredient + id: ginger +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169231' + url: https://fdc.nal.usda.gov/food-details/169231/nutrients + title: Ginger root, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169231 + data_type: SR Legacy + description: Ginger root, raw +nutrition_per_100g: + calcium_mg: 16.0 + carbohydrate_g: 17.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.0 + energy_kcal: 80.0 + iron_mg: 0.6 + potassium_mg: 415 + protein_g: 1.82 + saturated_fat_g: 0.203 + sodium_mg: 13.0 + total_fat_g: 0.75 + total_sugars_g: 1.7 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_ginger_ground_170926.yaml b/culinary/source_mappings/usda_fdc_ginger_ground_170926.yaml new file mode 100644 index 0000000..c4c5d1a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_ginger_ground_170926.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_ginger_ground_170926 +subject: + type: ingredient + id: ginger_ground +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170926' + url: https://fdc.nal.usda.gov/food-details/170926/nutrients + title: Spices, ginger, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170926 + data_type: SR Legacy + description: Spices, ginger, ground +nutrition_per_100g: + calcium_mg: 114 + carbohydrate_g: 71.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 14.1 + energy_kcal: 335 + iron_mg: 19.8 + potassium_mg: 1320.0 + protein_g: 8.98 + saturated_fat_g: 2.6 + sodium_mg: 27.0 + total_fat_g: 4.24 + total_sugars_g: 3.39 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_glucose_1983545.yaml b/culinary/source_mappings/usda_fdc_glucose_1983545.yaml new file mode 100644 index 0000000..d5ce23a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_glucose_1983545.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_glucose_1983545 +subject: + type: ingredient + id: glucose +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1983545' + url: https://fdc.nal.usda.gov/food-details/1983545/nutrients + title: GLUCOSE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1983545 + data_type: Branded + description: GLUCOSE + brand_owner: Wilton Industries Inc. + gtin_upc: 070896725981 +nutrition_per_100g: + carbohydrate_g: 106.67 + energy_kcal: 433.0 + protein_g: 0.0 + sodium_mg: 133.0 + total_fat_g: 0.0 + total_sugars_g: 43.33 diff --git a/culinary/source_mappings/usda_fdc_graham_cracker_174957.yaml b/culinary/source_mappings/usda_fdc_graham_cracker_174957.yaml new file mode 100644 index 0000000..ce1b110 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_graham_cracker_174957.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_graham_cracker_174957 +subject: + type: ingredient + id: graham_cracker +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174957' + url: https://fdc.nal.usda.gov/food-details/174957/nutrients + title: Cookies, graham crackers, plain or honey (includes cinnamon) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174957 + data_type: SR Legacy + description: Cookies, graham crackers, plain or honey (includes cinnamon) +nutrition_per_100g: + calcium_mg: 77.0 + carbohydrate_g: 77.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 3.4 + energy_kcal: 430 + iron_mg: 3.78 + potassium_mg: 170 + protein_g: 6.69 + saturated_fat_g: 1.63 + sodium_mg: 516 + total_fat_g: 10.6 + total_sugars_g: 24.8 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_green_onion_2727585.yaml b/culinary/source_mappings/usda_fdc_green_onion_2727585.yaml new file mode 100644 index 0000000..c185faf --- /dev/null +++ b/culinary/source_mappings/usda_fdc_green_onion_2727585.yaml @@ -0,0 +1,27 @@ +schema_version: 2 +id: usda_fdc_green_onion_2727585 +subject: + type: ingredient + id: green_onion +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2727585' + url: https://fdc.nal.usda.gov/food-details/2727585/nutrients + title: Green onion, (scallion), bulb and greens, root removed, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2727585 + data_type: Foundation + description: Green onion, (scallion), bulb and greens, root removed, raw +nutrition_per_100g: + calcium_mg: 59.4 + dietary_fiber_g: 2.3 + iron_mg: 1.04 + potassium_mg: 232 + protein_g: 0.669 + sodium_mg: 9.95 diff --git a/culinary/source_mappings/usda_fdc_ground_beef_73_27_raw_2450404.yaml b/culinary/source_mappings/usda_fdc_ground_beef_73_27_raw_2450404.yaml new file mode 100644 index 0000000..5245994 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_ground_beef_73_27_raw_2450404.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_ground_beef_73_27_raw_2450404 +subject: + type: ingredient + id: ground_beef_73_27_raw +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2450404' + url: https://fdc.nal.usda.gov/food-details/2450404/nutrients + title: 73% LEAN 27% FAT GROUND BEEF + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2450404 + data_type: Branded + description: 73% LEAN 27% FAT GROUND BEEF + brand_owner: Meijer, Inc. + gtin_upc: '708820974548' +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 76.0 + energy_kcal: 304.0 + iron_mg: 1.79 + potassium_mg: 233.0 + protein_g: 15.18 + saturated_fat_g: 10.71 + sodium_mg: 67.0 + total_fat_g: 26.79 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_heavy_cream_2346386.yaml b/culinary/source_mappings/usda_fdc_heavy_cream_2346386.yaml new file mode 100644 index 0000000..54d2d42 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_heavy_cream_2346386.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_heavy_cream_2346386 +subject: + type: ingredient + id: heavy_cream +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346386' + url: https://fdc.nal.usda.gov/food-details/2346386/nutrients + title: Cream, heavy + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346386 + data_type: Foundation + description: Cream, heavy +nutrition_per_100g: + calcium_mg: 61.2 + carbohydrate_g: 3.8 + cholesterol_mg: 103 + energy_kcal: 336 + iron_mg: 0.0 + potassium_mg: 96.9 + protein_g: 2.02 + saturated_fat_g: 20.4 + sodium_mg: 20.6 + total_fat_g: 35.6 diff --git a/culinary/source_mappings/usda_fdc_hidden_valley_ranch_dry_seasoning_2546792.yaml b/culinary/source_mappings/usda_fdc_hidden_valley_ranch_dry_seasoning_2546792.yaml new file mode 100644 index 0000000..7cd28ea --- /dev/null +++ b/culinary/source_mappings/usda_fdc_hidden_valley_ranch_dry_seasoning_2546792.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_hidden_valley_ranch_dry_seasoning_2546792 +subject: + type: ingredient + id: hidden_valley_ranch_dry_seasoning +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2546792' + url: https://fdc.nal.usda.gov/food-details/2546792/nutrients + title: RANCH SEASONING & SALAD DRESSING MIX, RANCH + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2546792 + data_type: Branded + description: RANCH SEASONING & SALAD DRESSING MIX, RANCH + brand_owner: The Hvr Company + gtin_upc: 071100309744 +nutrition_per_100g: + carbohydrate_g: 0.0 + energy_kcal: 0.0 + protein_g: 0.0 + sodium_mg: 7500.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_honey_169640.yaml b/culinary/source_mappings/usda_fdc_honey_169640.yaml new file mode 100644 index 0000000..e1aacd4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_honey_169640.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_honey_169640 +subject: + type: ingredient + id: honey +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169640' + url: https://fdc.nal.usda.gov/food-details/169640/nutrients + title: Honey + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169640 + data_type: SR Legacy + description: Honey +nutrition_per_100g: + calcium_mg: 6.0 + carbohydrate_g: 82.4 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.2 + energy_kcal: 304 + iron_mg: 0.42 + potassium_mg: 52.0 + protein_g: 0.3 + saturated_fat_g: 0.0 + sodium_mg: 4.0 + total_fat_g: 0.0 + total_sugars_g: 82.1 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_hot_cherry_peppers_169766.yaml b/culinary/source_mappings/usda_fdc_hot_cherry_peppers_169766.yaml new file mode 100644 index 0000000..403dcc1 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_hot_cherry_peppers_169766.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_hot_cherry_peppers_169766 +subject: + type: ingredient + id: hot_cherry_peppers +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169766' + url: https://fdc.nal.usda.gov/food-details/169766/nutrients + title: Peppers, hot pickled, canned + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169766 + data_type: SR Legacy + description: Peppers, hot pickled, canned +nutrition_per_100g: + calcium_mg: 61.0 + carbohydrate_g: 4.56 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.6 + energy_kcal: 22.0 + iron_mg: 0.32 + potassium_mg: 113 + protein_g: 0.8 + saturated_fat_g: 0.061 + sodium_mg: 1430.0 + total_fat_g: 0.4 + total_sugars_g: 1.6 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_hot_sauce_174527.yaml b/culinary/source_mappings/usda_fdc_hot_sauce_174527.yaml new file mode 100644 index 0000000..82bb618 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_hot_sauce_174527.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_hot_sauce_174527 +subject: + type: ingredient + id: hot_sauce +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174527' + url: https://fdc.nal.usda.gov/food-details/174527/nutrients + title: Sauce, ready-to-serve, pepper or hot + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174527 + data_type: SR Legacy + description: Sauce, ready-to-serve, pepper or hot +nutrition_per_100g: + calcium_mg: 8.0 + carbohydrate_g: 1.75 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.3 + energy_kcal: 11.0 + iron_mg: 0.48 + potassium_mg: 144 + protein_g: 0.51 + saturated_fat_g: 0.052 + sodium_mg: 2640.0 + total_fat_g: 0.37 + total_sugars_g: 1.26 diff --git a/culinary/source_mappings/usda_fdc_imitation_crab_174203.yaml b/culinary/source_mappings/usda_fdc_imitation_crab_174203.yaml new file mode 100644 index 0000000..839737a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_imitation_crab_174203.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_imitation_crab_174203 +subject: + type: ingredient + id: imitation_crab +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174203' + url: https://fdc.nal.usda.gov/food-details/174203/nutrients + title: Crustaceans, crab, alaska king, imitation, made from surimi + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174203 + data_type: SR Legacy + description: Crustaceans, crab, alaska king, imitation, made from surimi +nutrition_per_100g: + calcium_mg: 13.0 + carbohydrate_g: 15.0 + cholesterol_mg: 20.0 + dietary_fiber_g: 0.5 + energy_kcal: 95.0 + iron_mg: 0.39 + potassium_mg: 90.0 + protein_g: 7.62 + saturated_fat_g: 0.216 + sodium_mg: 529 + total_fat_g: 0.46 + total_sugars_g: 6.25 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_instant_yeast_175043.yaml b/culinary/source_mappings/usda_fdc_instant_yeast_175043.yaml new file mode 100644 index 0000000..75e63ee --- /dev/null +++ b/culinary/source_mappings/usda_fdc_instant_yeast_175043.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_instant_yeast_175043 +subject: + type: ingredient + id: instant_yeast +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '175043' + url: https://fdc.nal.usda.gov/food-details/175043/nutrients + title: Leavening agents, yeast, baker's, active dry + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 175043 + data_type: SR Legacy + description: Leavening agents, yeast, baker's, active dry +nutrition_per_100g: + calcium_mg: 30.0 + carbohydrate_g: 41.22 + cholesterol_mg: 0.0 + dietary_fiber_g: 26.9 + energy_kcal: 325.0 + iron_mg: 2.17 + potassium_mg: 955.0 + protein_g: 40.44 + saturated_fat_g: 1.001 + sodium_mg: 51.0 + total_fat_g: 7.61 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_italian_sausage_171631.yaml b/culinary/source_mappings/usda_fdc_italian_sausage_171631.yaml new file mode 100644 index 0000000..36a2918 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_italian_sausage_171631.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_italian_sausage_171631 +subject: + type: ingredient + id: italian_sausage +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171631' + url: https://fdc.nal.usda.gov/food-details/171631/nutrients + title: Sausage, Italian, pork, mild, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171631 + data_type: SR Legacy + description: Sausage, Italian, pork, mild, raw +nutrition_per_100g: + calcium_mg: 12.0 + carbohydrate_g: 2.97 + cholesterol_mg: 69.0 + dietary_fiber_g: 0.0 + energy_kcal: 290 + iron_mg: 1.77 + potassium_mg: 211 + protein_g: 13.9 + saturated_fat_g: 8.62 + sodium_mg: 563 + total_fat_g: 24.3 + total_sugars_g: 1.19 diff --git a/culinary/source_mappings/usda_fdc_jalapeno_peppers_pickled_170080.yaml b/culinary/source_mappings/usda_fdc_jalapeno_peppers_pickled_170080.yaml new file mode 100644 index 0000000..f452d21 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_jalapeno_peppers_pickled_170080.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_jalapeno_peppers_pickled_170080 +subject: + type: ingredient + id: jalapeno_peppers_pickled +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170080' + url: https://fdc.nal.usda.gov/food-details/170080/nutrients + title: Peppers, jalapeno, canned, solids and liquids + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170080 + data_type: SR Legacy + description: Peppers, jalapeno, canned, solids and liquids +nutrition_per_100g: + calcium_mg: 23.0 + carbohydrate_g: 4.74 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.6 + energy_kcal: 27.0 + iron_mg: 1.88 + potassium_mg: 193 + protein_g: 0.92 + saturated_fat_g: 0.097 + sodium_mg: 1670.0 + total_fat_g: 0.94 + total_sugars_g: 2.14 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_ketchup_168556.yaml b/culinary/source_mappings/usda_fdc_ketchup_168556.yaml new file mode 100644 index 0000000..e8ad7b9 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_ketchup_168556.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_ketchup_168556 +subject: + type: ingredient + id: ketchup +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168556' + url: https://fdc.nal.usda.gov/food-details/168556/nutrients + title: Catsup + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168556 + data_type: SR Legacy + description: Catsup +nutrition_per_100g: + calcium_mg: 15.0 + carbohydrate_g: 27.4 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.3 + energy_kcal: 101 + iron_mg: 0.35 + potassium_mg: 281 + protein_g: 1.04 + saturated_fat_g: 0.014 + sodium_mg: 907 + total_fat_g: 0.1 + total_sugars_g: 21.3 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_lard_171401.yaml b/culinary/source_mappings/usda_fdc_lard_171401.yaml new file mode 100644 index 0000000..328c612 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lard_171401.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lard_171401 +subject: + type: ingredient + id: lard +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171401' + url: https://fdc.nal.usda.gov/food-details/171401/nutrients + title: Lard + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171401 + data_type: SR Legacy + description: Lard +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 95.0 + dietary_fiber_g: 0.0 + energy_kcal: 902 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 39.2 + sodium_mg: 0.0 + total_fat_g: 100 + total_sugars_g: 0.0 + vitamin_d_mcg: 2.5 diff --git a/culinary/source_mappings/usda_fdc_lecithin_171426.yaml b/culinary/source_mappings/usda_fdc_lecithin_171426.yaml new file mode 100644 index 0000000..d8f70ef --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lecithin_171426.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lecithin_171426 +subject: + type: ingredient + id: lecithin +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171426' + url: https://fdc.nal.usda.gov/food-details/171426/nutrients + title: Oil, soybean lecithin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171426 + data_type: SR Legacy + description: Oil, soybean lecithin +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 763 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 15.0 + sodium_mg: 0.0 + total_fat_g: 100 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_lecithin_powder_2125978.yaml b/culinary/source_mappings/usda_fdc_lecithin_powder_2125978.yaml new file mode 100644 index 0000000..15a9d9b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lecithin_powder_2125978.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lecithin_powder_2125978 +subject: + type: ingredient + id: lecithin_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2125978' + url: https://fdc.nal.usda.gov/food-details/2125978/nutrients + title: BOB'S RED MILL, SOY LECITHIN GRANULES + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2125978 + data_type: Branded + description: BOB'S RED MILL, SOY LECITHIN GRANULES + brand_owner: Bob's Red Mill Natural Foods, Inc. + gtin_upc: 039978005182 +nutrition_per_100g: + calcium_mg: 250.0 + carbohydrate_g: 12.5 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 750.0 + iron_mg: 4.5 + protein_g: 0.0 + saturated_fat_g: 12.5 + sodium_mg: 0.0 + total_fat_g: 50.0 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_lemon_juice_167747.yaml b/culinary/source_mappings/usda_fdc_lemon_juice_167747.yaml new file mode 100644 index 0000000..59552b2 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lemon_juice_167747.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lemon_juice_167747 +subject: + type: ingredient + id: lemon_juice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '167747' + url: https://fdc.nal.usda.gov/food-details/167747/nutrients + title: Lemon juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 167747 + data_type: SR Legacy + description: Lemon juice, raw +nutrition_per_100g: + calcium_mg: 6.0 + carbohydrate_g: 6.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.3 + energy_kcal: 22.0 + iron_mg: 0.08 + potassium_mg: 103 + protein_g: 0.35 + saturated_fat_g: 0.04 + sodium_mg: 1.0 + total_fat_g: 0.24 + total_sugars_g: 2.52 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_lemon_zest_167749.yaml b/culinary/source_mappings/usda_fdc_lemon_zest_167749.yaml new file mode 100644 index 0000000..d64bbaa --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lemon_zest_167749.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lemon_zest_167749 +subject: + type: ingredient + id: lemon_zest +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '167749' + url: https://fdc.nal.usda.gov/food-details/167749/nutrients + title: Lemon peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 167749 + data_type: SR Legacy + description: Lemon peel, raw +nutrition_per_100g: + calcium_mg: 134 + carbohydrate_g: 16.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 10.6 + energy_kcal: 47.0 + iron_mg: 0.8 + potassium_mg: 160 + protein_g: 1.5 + saturated_fat_g: 0.039 + sodium_mg: 6.0 + total_fat_g: 0.3 + total_sugars_g: 4.17 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_lime_juice_168156.yaml b/culinary/source_mappings/usda_fdc_lime_juice_168156.yaml new file mode 100644 index 0000000..cba6801 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_lime_juice_168156.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_lime_juice_168156 +subject: + type: ingredient + id: lime_juice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168156' + url: https://fdc.nal.usda.gov/food-details/168156/nutrients + title: Lime juice, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168156 + data_type: SR Legacy + description: Lime juice, raw +nutrition_per_100g: + calcium_mg: 14.0 + carbohydrate_g: 8.42 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.4 + energy_kcal: 25.0 + iron_mg: 0.09 + potassium_mg: 117 + protein_g: 0.42 + saturated_fat_g: 0.008 + sodium_mg: 2.0 + total_fat_g: 0.07 + total_sugars_g: 1.69 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_liquid_sunflower_lecithin_2373459.yaml b/culinary/source_mappings/usda_fdc_liquid_sunflower_lecithin_2373459.yaml new file mode 100644 index 0000000..4f8ec5e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_liquid_sunflower_lecithin_2373459.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_liquid_sunflower_lecithin_2373459 +subject: + type: ingredient + id: liquid_sunflower_lecithin +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2373459' + url: https://fdc.nal.usda.gov/food-details/2373459/nutrients + title: LIQUID SUNFLOWER LECITHIN + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2373459 + data_type: Branded + description: LIQUID SUNFLOWER LECITHIN + brand_owner: Legendairy Milk, LLC + gtin_upc: '853792007241' +nutrition_per_100g: + calcium_mg: 250.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 833.0 + iron_mg: 0.0 + potassium_mg: 867.0 + protein_g: 0.0 + saturated_fat_g: 8.33 + sodium_mg: 0.0 + total_fat_g: 83.33 diff --git a/culinary/source_mappings/usda_fdc_mace_nutmeg_170927.yaml b/culinary/source_mappings/usda_fdc_mace_nutmeg_170927.yaml new file mode 100644 index 0000000..ee6457c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mace_nutmeg_170927.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_mace_nutmeg_170927 +subject: + type: ingredient + id: mace_nutmeg +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170927' + url: https://fdc.nal.usda.gov/food-details/170927/nutrients + title: Spices, mace, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170927 + data_type: SR Legacy + description: Spices, mace, ground +nutrition_per_100g: + calcium_mg: 252 + carbohydrate_g: 50.5 + cholesterol_mg: 0.0 + dietary_fiber_g: 20.2 + energy_kcal: 475 + iron_mg: 13.9 + potassium_mg: 463 + protein_g: 6.71 + saturated_fat_g: 9.51 + sodium_mg: 80.0 + total_fat_g: 32.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_marjoram_170928.yaml b/culinary/source_mappings/usda_fdc_marjoram_170928.yaml new file mode 100644 index 0000000..2f25903 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_marjoram_170928.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_marjoram_170928 +subject: + type: ingredient + id: marjoram +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170928' + url: https://fdc.nal.usda.gov/food-details/170928/nutrients + title: Spices, marjoram, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170928 + data_type: SR Legacy + description: Spices, marjoram, dried +nutrition_per_100g: + calcium_mg: 1990.0 + carbohydrate_g: 60.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 40.3 + energy_kcal: 271 + iron_mg: 82.7 + potassium_mg: 1520.0 + protein_g: 12.7 + saturated_fat_g: 0.529 + sodium_mg: 77.0 + total_fat_g: 7.04 + total_sugars_g: 4.09 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_mayonnaise_171009.yaml b/culinary/source_mappings/usda_fdc_mayonnaise_171009.yaml new file mode 100644 index 0000000..40267da --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mayonnaise_171009.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_mayonnaise_171009 +subject: + type: ingredient + id: mayonnaise +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171009' + url: https://fdc.nal.usda.gov/food-details/171009/nutrients + title: Salad dressing, mayonnaise, regular + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171009 + data_type: SR Legacy + description: Salad dressing, mayonnaise, regular +nutrition_per_100g: + calcium_mg: 8.0 + carbohydrate_g: 0.57 + cholesterol_mg: 42.0 + dietary_fiber_g: 0.0 + energy_kcal: 680 + iron_mg: 0.21 + potassium_mg: 20.0 + protein_g: 0.96 + saturated_fat_g: 11.7 + sodium_mg: 635 + total_fat_g: 74.8 + total_sugars_g: 0.57 + vitamin_d_mcg: 0.2 diff --git a/culinary/source_mappings/usda_fdc_michiu_wine_468381.yaml b/culinary/source_mappings/usda_fdc_michiu_wine_468381.yaml new file mode 100644 index 0000000..61e6dd9 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_michiu_wine_468381.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_michiu_wine_468381 +subject: + type: ingredient + id: michiu_wine +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '468381' + url: https://fdc.nal.usda.gov/food-details/468381/nutrients + title: COOKING RICE WINE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 468381 + data_type: Branded + description: COOKING RICE WINE + brand_owner: DAIEI TRADING + gtin_upc: '4902856311070' +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 6.67 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 67.0 + iron_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 667.0 + total_fat_g: 0.0 + total_sugars_g: 6.67 diff --git a/culinary/source_mappings/usda_fdc_milk_746778.yaml b/culinary/source_mappings/usda_fdc_milk_746778.yaml new file mode 100644 index 0000000..bc87c97 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_milk_746778.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_milk_746778 +subject: + type: ingredient + id: milk +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '746778' + url: https://fdc.nal.usda.gov/food-details/746778/nutrients + title: Milk, reduced fat, fluid, 2% milkfat, with added vitamin A and vitamin D + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 746778 + data_type: Foundation + description: Milk, reduced fat, fluid, 2% milkfat, with added vitamin A and vitamin + D +nutrition_per_100g: + calcium_mg: 126 + carbohydrate_g: 4.9 + cholesterol_mg: 8.0 + energy_kcal: 50.0 + iron_mg: 0.0 + potassium_mg: 159 + protein_g: 3.36 + saturated_fat_g: 1.11 + sodium_mg: 39.0 + total_fat_g: 1.9 + vitamin_d_mcg: 1.13 diff --git a/culinary/source_mappings/usda_fdc_milk_powder_whole_2491279.yaml b/culinary/source_mappings/usda_fdc_milk_powder_whole_2491279.yaml new file mode 100644 index 0000000..3057844 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_milk_powder_whole_2491279.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_milk_powder_whole_2491279 +subject: + type: ingredient + id: milk_powder_whole +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2491279' + url: https://fdc.nal.usda.gov/food-details/2491279/nutrients + title: DRY WHOLE POWDERED MILK + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2491279 + data_type: Branded + description: DRY WHOLE POWDERED MILK + brand_owner: The B.P. Of Miami, Inc. + gtin_upc: '852139000396' +nutrition_per_100g: + calcium_mg: 833.0 + carbohydrate_g: 40.0 + cholesterol_mg: 100.0 + dietary_fiber_g: 0.0 + energy_kcal: 500.0 + iron_mg: 0.0 + protein_g: 26.67 + saturated_fat_g: 16.67 + sodium_mg: 367.0 + total_fat_g: 26.67 + total_sugars_g: 40.0 diff --git a/culinary/source_mappings/usda_fdc_mint_dried_172239.yaml b/culinary/source_mappings/usda_fdc_mint_dried_172239.yaml new file mode 100644 index 0000000..f7ce8f1 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mint_dried_172239.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_mint_dried_172239 +subject: + type: ingredient + id: mint_dried +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172239' + url: https://fdc.nal.usda.gov/food-details/172239/nutrients + title: Spearmint, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172239 + data_type: SR Legacy + description: Spearmint, dried +nutrition_per_100g: + calcium_mg: 1488.0 + carbohydrate_g: 52.04 + cholesterol_mg: 0.0 + dietary_fiber_g: 29.8 + energy_kcal: 285.0 + iron_mg: 87.47 + potassium_mg: 1924.0 + protein_g: 19.93 + saturated_fat_g: 1.577 + sodium_mg: 344.0 + total_fat_g: 6.03 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_molasses_168820.yaml b/culinary/source_mappings/usda_fdc_molasses_168820.yaml new file mode 100644 index 0000000..39a2efe --- /dev/null +++ b/culinary/source_mappings/usda_fdc_molasses_168820.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_molasses_168820 +subject: + type: ingredient + id: molasses +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168820' + url: https://fdc.nal.usda.gov/food-details/168820/nutrients + title: Molasses + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168820 + data_type: SR Legacy + description: Molasses +nutrition_per_100g: + calcium_mg: 205 + carbohydrate_g: 74.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 290 + iron_mg: 4.72 + potassium_mg: 1460.0 + protein_g: 0.0 + saturated_fat_g: 0.018 + sodium_mg: 37.0 + total_fat_g: 0.1 + total_sugars_g: 74.7 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_monterey_jack_cheese_2647438.yaml b/culinary/source_mappings/usda_fdc_monterey_jack_cheese_2647438.yaml new file mode 100644 index 0000000..868d0da --- /dev/null +++ b/culinary/source_mappings/usda_fdc_monterey_jack_cheese_2647438.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_monterey_jack_cheese_2647438 +subject: + type: ingredient + id: monterey_jack_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2647438' + url: https://fdc.nal.usda.gov/food-details/2647438/nutrients + title: Cheese, monterey jack, solid + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2647438 + data_type: Foundation + description: Cheese, monterey jack, solid +nutrition_per_100g: + calcium_mg: 715 + carbohydrate_g: 1.9 + cholesterol_mg: 99.8 + energy_kcal: 391 + iron_mg: 0.0 + potassium_mg: 82.9 + protein_g: 22.6 + saturated_fat_g: 19.2 + sodium_mg: 662 + total_fat_g: 32.6 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_mozzarella_cheese_329370.yaml b/culinary/source_mappings/usda_fdc_mozzarella_cheese_329370.yaml new file mode 100644 index 0000000..52858ff --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mozzarella_cheese_329370.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_mozzarella_cheese_329370 +subject: + type: ingredient + id: mozzarella_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '329370' + url: https://fdc.nal.usda.gov/food-details/329370/nutrients + title: Cheese, mozzarella, low moisture, part-skim + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 329370 + data_type: Foundation + description: Cheese, mozzarella, low moisture, part-skim +nutrition_per_100g: + calcium_mg: 693 + carbohydrate_g: 4.44 + cholesterol_mg: 65.0 + energy_kcal: 298 + iron_mg: 0.2 + potassium_mg: 116 + protein_g: 23.7 + saturated_fat_g: 11.7 + sodium_mg: 699 + total_fat_g: 20.4 diff --git a/culinary/source_mappings/usda_fdc_msg_2449440.yaml b/culinary/source_mappings/usda_fdc_msg_2449440.yaml new file mode 100644 index 0000000..428a335 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_msg_2449440.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_msg_2449440 +subject: + type: ingredient + id: msg +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2449440' + url: https://fdc.nal.usda.gov/food-details/2449440/nutrients + title: MSG MONOSODIUM GLUTAMATE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2449440 + data_type: Branded + description: MSG MONOSODIUM GLUTAMATE + brand_owner: Smart & Final Iris Corporation + gtin_upc: '041512143465' +nutrition_per_100g: + carbohydrate_g: 0.0 + energy_kcal: 0.0 + protein_g: 0.0 + sodium_mg: 12500.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_mustard_dijon_2029577.yaml b/culinary/source_mappings/usda_fdc_mustard_dijon_2029577.yaml new file mode 100644 index 0000000..c9480a0 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mustard_dijon_2029577.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_mustard_dijon_2029577 +subject: + type: ingredient + id: mustard_dijon +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2029577' + url: https://fdc.nal.usda.gov/food-details/2029577/nutrients + title: DIJON MUSTARD + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2029577 + data_type: Branded + description: DIJON MUSTARD + brand_owner: Winco Foods, Inc. + gtin_upc: 070552701229 +nutrition_per_100g: + carbohydrate_g: 0.0 + energy_kcal: 100.0 + protein_g: 0.0 + sodium_mg: 2400.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_mustard_yellow_326698.yaml b/culinary/source_mappings/usda_fdc_mustard_yellow_326698.yaml new file mode 100644 index 0000000..18dcf3a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_mustard_yellow_326698.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_mustard_yellow_326698 +subject: + type: ingredient + id: mustard_yellow +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '326698' + url: https://fdc.nal.usda.gov/food-details/326698/nutrients + title: Mustard, prepared, yellow + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 326698 + data_type: Foundation + description: Mustard, prepared, yellow +nutrition_per_100g: + calcium_mg: 63.0 + carbohydrate_g: 5.3 + dietary_fiber_g: 4.3 + energy_kcal: 61.0 + iron_mg: 1.59 + potassium_mg: 150 + protein_g: 4.25 + saturated_fat_g: 0.252 + sodium_mg: 1100.0 + total_fat_g: 3.38 diff --git a/culinary/source_mappings/usda_fdc_nonfat_milk_powder_171273.yaml b/culinary/source_mappings/usda_fdc_nonfat_milk_powder_171273.yaml new file mode 100644 index 0000000..5b5d53e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_nonfat_milk_powder_171273.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_nonfat_milk_powder_171273 +subject: + type: ingredient + id: nonfat_milk_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171273' + url: https://fdc.nal.usda.gov/food-details/171273/nutrients + title: Milk, dry, nonfat, calcium reduced + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171273 + data_type: SR Legacy + description: Milk, dry, nonfat, calcium reduced +nutrition_per_100g: + calcium_mg: 280 + carbohydrate_g: 51.8 + cholesterol_mg: 2.0 + dietary_fiber_g: 0.0 + energy_kcal: 354 + iron_mg: 0.32 + potassium_mg: 680 + protein_g: 35.5 + saturated_fat_g: 0.124 + sodium_mg: 2280.0 + total_fat_g: 0.2 diff --git a/culinary/source_mappings/usda_fdc_nutmeg_171326.yaml b/culinary/source_mappings/usda_fdc_nutmeg_171326.yaml new file mode 100644 index 0000000..b3fdc06 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_nutmeg_171326.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_nutmeg_171326 +subject: + type: ingredient + id: nutmeg +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171326' + url: https://fdc.nal.usda.gov/food-details/171326/nutrients + title: Spices, nutmeg, ground + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171326 + data_type: SR Legacy + description: Spices, nutmeg, ground +nutrition_per_100g: + calcium_mg: 184 + carbohydrate_g: 49.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 20.8 + energy_kcal: 525 + iron_mg: 3.04 + potassium_mg: 350 + protein_g: 5.84 + saturated_fat_g: 25.9 + sodium_mg: 16.0 + total_fat_g: 36.3 + total_sugars_g: 2.99 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_oats_2346396.yaml b/culinary/source_mappings/usda_fdc_oats_2346396.yaml new file mode 100644 index 0000000..4607165 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_oats_2346396.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_oats_2346396 +subject: + type: ingredient + id: oats +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346396' + url: https://fdc.nal.usda.gov/food-details/2346396/nutrients + title: Oats, whole grain, rolled, old fashioned + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346396 + data_type: Foundation + description: Oats, whole grain, rolled, old fashioned +nutrition_per_100g: + calcium_mg: 45.5 + carbohydrate_g: 68.7 + energy_kcal: 379 + iron_mg: 4.34 + potassium_mg: 350 + protein_g: 13.5 + sodium_mg: 0.668 + total_fat_g: 5.89 diff --git a/culinary/source_mappings/usda_fdc_olive_oil_748608.yaml b/culinary/source_mappings/usda_fdc_olive_oil_748608.yaml new file mode 100644 index 0000000..27a0137 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_olive_oil_748608.yaml @@ -0,0 +1,22 @@ +schema_version: 2 +id: usda_fdc_olive_oil_748608 +subject: + type: ingredient + id: olive_oil +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '748608' + url: https://fdc.nal.usda.gov/food-details/748608/nutrients + title: Oil, olive, extra virgin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 748608 + data_type: Foundation + description: Oil, olive, extra virgin +nutrition_per_100g: + saturated_fat_g: 15.4 diff --git a/culinary/source_mappings/usda_fdc_onion_dehydrated_flake_170002.yaml b/culinary/source_mappings/usda_fdc_onion_dehydrated_flake_170002.yaml new file mode 100644 index 0000000..eee6aea --- /dev/null +++ b/culinary/source_mappings/usda_fdc_onion_dehydrated_flake_170002.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_onion_dehydrated_flake_170002 +subject: + type: ingredient + id: onion_dehydrated_flake +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170002' + url: https://fdc.nal.usda.gov/food-details/170002/nutrients + title: Onions, dehydrated flakes + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170002 + data_type: SR Legacy + description: Onions, dehydrated flakes +nutrition_per_100g: + calcium_mg: 257 + carbohydrate_g: 83.3 + cholesterol_mg: 0.0 + dietary_fiber_g: 9.2 + energy_kcal: 349 + iron_mg: 1.55 + potassium_mg: 1620.0 + protein_g: 8.95 + saturated_fat_g: 0.078 + sodium_mg: 21.0 + total_fat_g: 0.46 + total_sugars_g: 37.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_onion_dehydrated_powder_171327.yaml b/culinary/source_mappings/usda_fdc_onion_dehydrated_powder_171327.yaml new file mode 100644 index 0000000..22326d5 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_onion_dehydrated_powder_171327.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_onion_dehydrated_powder_171327 +subject: + type: ingredient + id: onion_dehydrated_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/nutrients + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171327 + data_type: SR Legacy + description: Spices, onion powder +nutrition_per_100g: + calcium_mg: 384 + carbohydrate_g: 79.1 + cholesterol_mg: 0.0 + dietary_fiber_g: 15.2 + energy_kcal: 341 + iron_mg: 3.9 + potassium_mg: 985 + protein_g: 10.4 + saturated_fat_g: 0.219 + sodium_mg: 73.0 + total_fat_g: 1.04 + total_sugars_g: 6.63 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_onion_powder_171327.yaml b/culinary/source_mappings/usda_fdc_onion_powder_171327.yaml new file mode 100644 index 0000000..95342a2 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_onion_powder_171327.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_onion_powder_171327 +subject: + type: ingredient + id: onion_powder +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171327' + url: https://fdc.nal.usda.gov/food-details/171327/nutrients + title: Spices, onion powder + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171327 + data_type: SR Legacy + description: Spices, onion powder +nutrition_per_100g: + calcium_mg: 384 + carbohydrate_g: 79.1 + cholesterol_mg: 0.0 + dietary_fiber_g: 15.2 + energy_kcal: 341 + iron_mg: 3.9 + potassium_mg: 985 + protein_g: 10.4 + saturated_fat_g: 0.219 + sodium_mg: 73.0 + total_fat_g: 1.04 + total_sugars_g: 6.63 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_onion_yellow_790646.yaml b/culinary/source_mappings/usda_fdc_onion_yellow_790646.yaml new file mode 100644 index 0000000..26bd84e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_onion_yellow_790646.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_onion_yellow_790646 +subject: + type: ingredient + id: onion_yellow +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '790646' + url: https://fdc.nal.usda.gov/food-details/790646/nutrients + title: Onions, yellow, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 790646 + data_type: Foundation + description: Onions, yellow, raw +nutrition_per_100g: + calcium_mg: 15.0 + carbohydrate_g: 8.61 + dietary_fiber_g: 1.9 + energy_kcal: 38.0 + iron_mg: 0.28 + potassium_mg: 182.0 + protein_g: 0.83 + sodium_mg: 1.0 + total_fat_g: 0.05 diff --git a/culinary/source_mappings/usda_fdc_orange_juice_2003597.yaml b/culinary/source_mappings/usda_fdc_orange_juice_2003597.yaml new file mode 100644 index 0000000..7e0c833 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_orange_juice_2003597.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_orange_juice_2003597 +subject: + type: ingredient + id: orange_juice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2003597' + url: https://fdc.nal.usda.gov/food-details/2003597/nutrients + title: Orange juice, no pulp, not fortified, not from concentrate, refrigerated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2003597 + data_type: Foundation + description: Orange juice, no pulp, not fortified, not from concentrate, refrigerated +nutrition_per_100g: + calcium_mg: 9.29 + carbohydrate_g: 10.0 + energy_kcal: 45.0 + iron_mg: 0.071 + potassium_mg: 183 + protein_g: 0.812 + sodium_mg: 0.075 + total_fat_g: 0.356 diff --git a/culinary/source_mappings/usda_fdc_orange_juice_concentrate_169923.yaml b/culinary/source_mappings/usda_fdc_orange_juice_concentrate_169923.yaml new file mode 100644 index 0000000..cdcadb8 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_orange_juice_concentrate_169923.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_orange_juice_concentrate_169923 +subject: + type: ingredient + id: orange_juice_concentrate +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169923' + url: https://fdc.nal.usda.gov/food-details/169923/nutrients + title: Orange juice, frozen concentrate, unsweetened, undiluted + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169923 + data_type: SR Legacy + description: Orange juice, frozen concentrate, unsweetened, undiluted +nutrition_per_100g: + calcium_mg: 38.0 + carbohydrate_g: 35.2 + cholesterol_mg: 0.0 + dietary_fiber_g: 1.0 + energy_kcal: 148 + iron_mg: 0.33 + potassium_mg: 629 + protein_g: 2.4 + saturated_fat_g: 0.059 + sodium_mg: 7.0 + total_fat_g: 0.25 + total_sugars_g: 29.7 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_orange_zest_169103.yaml b/culinary/source_mappings/usda_fdc_orange_zest_169103.yaml new file mode 100644 index 0000000..79df75b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_orange_zest_169103.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_orange_zest_169103 +subject: + type: ingredient + id: orange_zest +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169103' + url: https://fdc.nal.usda.gov/food-details/169103/nutrients + title: Orange peel, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169103 + data_type: SR Legacy + description: Orange peel, raw +nutrition_per_100g: + calcium_mg: 161 + carbohydrate_g: 25.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 10.6 + energy_kcal: 97.0 + iron_mg: 0.8 + potassium_mg: 212 + protein_g: 1.5 + saturated_fat_g: 0.024 + sodium_mg: 3.0 + total_fat_g: 0.2 diff --git a/culinary/source_mappings/usda_fdc_oregano_171328.yaml b/culinary/source_mappings/usda_fdc_oregano_171328.yaml new file mode 100644 index 0000000..2e63e63 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_oregano_171328.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_oregano_171328 +subject: + type: ingredient + id: oregano +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171328' + url: https://fdc.nal.usda.gov/food-details/171328/nutrients + title: Spices, oregano, dried + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171328 + data_type: SR Legacy + description: Spices, oregano, dried +nutrition_per_100g: + calcium_mg: 1600.0 + carbohydrate_g: 68.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 42.5 + energy_kcal: 265 + iron_mg: 36.8 + potassium_mg: 1260.0 + protein_g: 9.0 + saturated_fat_g: 1.55 + sodium_mg: 25.0 + total_fat_g: 4.28 + total_sugars_g: 4.09 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_oyster_sauce_174529.yaml b/culinary/source_mappings/usda_fdc_oyster_sauce_174529.yaml new file mode 100644 index 0000000..aa0681f --- /dev/null +++ b/culinary/source_mappings/usda_fdc_oyster_sauce_174529.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_oyster_sauce_174529 +subject: + type: ingredient + id: oyster_sauce +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174529' + url: https://fdc.nal.usda.gov/food-details/174529/nutrients + title: Sauce, oyster, ready-to-serve + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174529 + data_type: SR Legacy + description: Sauce, oyster, ready-to-serve +nutrition_per_100g: + calcium_mg: 32.0 + carbohydrate_g: 10.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.3 + energy_kcal: 51.0 + iron_mg: 0.18 + potassium_mg: 54.0 + protein_g: 1.35 + saturated_fat_g: 0.043 + sodium_mg: 2730.0 + total_fat_g: 0.25 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_paprika_171329.yaml b/culinary/source_mappings/usda_fdc_paprika_171329.yaml new file mode 100644 index 0000000..a788413 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_paprika_171329.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_paprika_171329 +subject: + type: ingredient + id: paprika +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171329' + url: https://fdc.nal.usda.gov/food-details/171329/nutrients + title: Spices, paprika + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171329 + data_type: SR Legacy + description: Spices, paprika +nutrition_per_100g: + calcium_mg: 229 + carbohydrate_g: 54.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 34.9 + energy_kcal: 282 + iron_mg: 21.1 + potassium_mg: 2280.0 + protein_g: 14.1 + saturated_fat_g: 2.14 + sodium_mg: 68.0 + total_fat_g: 12.9 + total_sugars_g: 10.3 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_parmesan_cheese_171247.yaml b/culinary/source_mappings/usda_fdc_parmesan_cheese_171247.yaml new file mode 100644 index 0000000..f6b3232 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_parmesan_cheese_171247.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_parmesan_cheese_171247 +subject: + type: ingredient + id: parmesan_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171247' + url: https://fdc.nal.usda.gov/food-details/171247/nutrients + title: Cheese, parmesan, grated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171247 + data_type: SR Legacy + description: Cheese, parmesan, grated +nutrition_per_100g: + calcium_mg: 853 + carbohydrate_g: 13.9 + cholesterol_mg: 86.0 + dietary_fiber_g: 0.0 + energy_kcal: 420 + iron_mg: 0.49 + potassium_mg: 180 + protein_g: 28.4 + saturated_fat_g: 15.4 + sodium_mg: 1800.0 + total_fat_g: 27.8 + total_sugars_g: 0.07 + vitamin_d_mcg: 0.5 diff --git a/culinary/source_mappings/usda_fdc_parsley_170416.yaml b/culinary/source_mappings/usda_fdc_parsley_170416.yaml new file mode 100644 index 0000000..c40a75f --- /dev/null +++ b/culinary/source_mappings/usda_fdc_parsley_170416.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_parsley_170416 +subject: + type: ingredient + id: parsley +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170416' + url: https://fdc.nal.usda.gov/food-details/170416/nutrients + title: Parsley, fresh + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170416 + data_type: SR Legacy + description: Parsley, fresh +nutrition_per_100g: + calcium_mg: 138 + carbohydrate_g: 6.33 + cholesterol_mg: 0.0 + dietary_fiber_g: 3.3 + energy_kcal: 36.0 + iron_mg: 6.2 + potassium_mg: 554 + protein_g: 2.97 + saturated_fat_g: 0.132 + sodium_mg: 56.0 + total_fat_g: 0.79 + total_sugars_g: 0.85 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_peanut_butter_2262072.yaml b/culinary/source_mappings/usda_fdc_peanut_butter_2262072.yaml new file mode 100644 index 0000000..5255c57 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_peanut_butter_2262072.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_peanut_butter_2262072 +subject: + type: ingredient + id: peanut_butter +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2262072' + url: https://fdc.nal.usda.gov/food-details/2262072/nutrients + title: Peanut butter, creamy + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2262072 + data_type: Foundation + description: Peanut butter, creamy +nutrition_per_100g: + calcium_mg: 49.8 + carbohydrate_g: 22.7 + dietary_fiber_g: 6.32 + energy_kcal: 589 + iron_mg: 1.85 + potassium_mg: 654 + protein_g: 24.0 + saturated_fat_g: 8.42 + sodium_mg: 221 + total_fat_g: 49.4 diff --git a/culinary/source_mappings/usda_fdc_pineapple_crushed_in_juice_169126.yaml b/culinary/source_mappings/usda_fdc_pineapple_crushed_in_juice_169126.yaml new file mode 100644 index 0000000..34a2fa6 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_pineapple_crushed_in_juice_169126.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_pineapple_crushed_in_juice_169126 +subject: + type: ingredient + id: pineapple_crushed_in_juice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '169126' + url: https://fdc.nal.usda.gov/food-details/169126/nutrients + title: Pineapple, canned, juice pack, solids and liquids + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 169126 + data_type: SR Legacy + description: Pineapple, canned, juice pack, solids and liquids +nutrition_per_100g: + calcium_mg: 14.0 + carbohydrate_g: 15.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.8 + energy_kcal: 60.0 + iron_mg: 0.28 + potassium_mg: 122 + protein_g: 0.42 + saturated_fat_g: 0.006 + sodium_mg: 1.0 + total_fat_g: 0.08 + total_sugars_g: 14.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_pinto_beans_dry_uncooked_747445.yaml b/culinary/source_mappings/usda_fdc_pinto_beans_dry_uncooked_747445.yaml new file mode 100644 index 0000000..789e81c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_pinto_beans_dry_uncooked_747445.yaml @@ -0,0 +1,27 @@ +schema_version: 2 +id: usda_fdc_pinto_beans_dry_uncooked_747445 +subject: + type: ingredient + id: pinto_beans_dry_uncooked +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '747445' + url: https://fdc.nal.usda.gov/food-details/747445/nutrients + title: Beans, Dry, Pinto (0% moisture) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 747445 + data_type: Foundation + description: Beans, Dry, Pinto (0% moisture) +nutrition_per_100g: + calcium_mg: 161 + dietary_fiber_g: 4.1 + iron_mg: 5.4 + potassium_mg: 1510.0 + protein_g: 23.7 + total_fat_g: 1.24 diff --git a/culinary/source_mappings/usda_fdc_pistachio_nuts_2515379.yaml b/culinary/source_mappings/usda_fdc_pistachio_nuts_2515379.yaml new file mode 100644 index 0000000..4680b5d --- /dev/null +++ b/culinary/source_mappings/usda_fdc_pistachio_nuts_2515379.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_pistachio_nuts_2515379 +subject: + type: ingredient + id: pistachio_nuts +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2515379' + url: https://fdc.nal.usda.gov/food-details/2515379/nutrients + title: Nuts, pistachio nuts, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2515379 + data_type: Foundation + description: Nuts, pistachio nuts, raw +nutrition_per_100g: + calcium_mg: 117 + carbohydrate_g: 27.7 + dietary_fiber_g: 6.97 + energy_kcal: 561 + iron_mg: 3.46 + potassium_mg: 947 + protein_g: 20.5 + sodium_mg: 0.0 + total_fat_g: 45.0 diff --git a/culinary/source_mappings/usda_fdc_potato_russet_170027.yaml b/culinary/source_mappings/usda_fdc_potato_russet_170027.yaml new file mode 100644 index 0000000..e1d6334 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_potato_russet_170027.yaml @@ -0,0 +1,36 @@ +schema_version: 2 +id: usda_fdc_potato_russet_170027 +subject: + type: ingredient + id: potato_russet +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170027' + url: https://fdc.nal.usda.gov/food-details/170027/nutrients + title: Potatoes, russet, flesh and skin, raw (Includes foods for USDA's Food Distribution + Program) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170027 + data_type: SR Legacy + description: Potatoes, russet, flesh and skin, raw (Includes foods for USDA's Food + Distribution Program) +nutrition_per_100g: + calcium_mg: 13.0 + carbohydrate_g: 18.1 + cholesterol_mg: 0.0 + dietary_fiber_g: 1.3 + energy_kcal: 79.0 + iron_mg: 0.86 + potassium_mg: 417 + protein_g: 2.14 + saturated_fat_g: 0.026 + sodium_mg: 5.0 + total_fat_g: 0.08 + total_sugars_g: 0.62 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_provolone_cheese_170850.yaml b/culinary/source_mappings/usda_fdc_provolone_cheese_170850.yaml new file mode 100644 index 0000000..cdf1d81 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_provolone_cheese_170850.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_provolone_cheese_170850 +subject: + type: ingredient + id: provolone_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170850' + url: https://fdc.nal.usda.gov/food-details/170850/nutrients + title: Cheese, provolone + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170850 + data_type: SR Legacy + description: Cheese, provolone +nutrition_per_100g: + calcium_mg: 756 + carbohydrate_g: 2.14 + cholesterol_mg: 69.0 + dietary_fiber_g: 0.0 + energy_kcal: 351 + iron_mg: 0.52 + potassium_mg: 138 + protein_g: 25.6 + saturated_fat_g: 17.1 + sodium_mg: 727 + total_fat_g: 26.6 + total_sugars_g: 0.56 + vitamin_d_mcg: 0.5 diff --git a/culinary/source_mappings/usda_fdc_pumpkin_puree_168450.yaml b/culinary/source_mappings/usda_fdc_pumpkin_puree_168450.yaml new file mode 100644 index 0000000..37b8fe6 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_pumpkin_puree_168450.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_pumpkin_puree_168450 +subject: + type: ingredient + id: pumpkin_puree +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168450' + url: https://fdc.nal.usda.gov/food-details/168450/nutrients + title: Pumpkin, canned, without salt + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168450 + data_type: SR Legacy + description: Pumpkin, canned, without salt +nutrition_per_100g: + calcium_mg: 26.0 + carbohydrate_g: 8.09 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.9 + energy_kcal: 34.0 + iron_mg: 1.39 + potassium_mg: 206 + protein_g: 1.1 + saturated_fat_g: 0.146 + sodium_mg: 5.0 + total_fat_g: 0.28 + total_sugars_g: 3.3 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_raisins_2758980.yaml b/culinary/source_mappings/usda_fdc_raisins_2758980.yaml new file mode 100644 index 0000000..eff2f10 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_raisins_2758980.yaml @@ -0,0 +1,26 @@ +schema_version: 2 +id: usda_fdc_raisins_2758980 +subject: + type: ingredient + id: raisins +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2758980' + url: https://fdc.nal.usda.gov/food-details/2758980/nutrients + title: Raisins, dark, seedless + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-12' + reviewed: true + reviewed_at: '2026-08-12' +usda: + fdc_id: 2758980 + data_type: Foundation + description: Raisins, dark, seedless +nutrition_per_100g: + calcium_mg: 51.49 + dietary_fiber_g: 3.679 + iron_mg: 1.844 + potassium_mg: 936.0 + sodium_mg: 13.17 diff --git a/culinary/source_mappings/usda_fdc_ranch_173592.yaml b/culinary/source_mappings/usda_fdc_ranch_173592.yaml new file mode 100644 index 0000000..f66c4e8 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_ranch_173592.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_ranch_173592 +subject: + type: ingredient + id: ranch +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '173592' + url: https://fdc.nal.usda.gov/food-details/173592/nutrients + title: Salad dressing, ranch dressing, regular + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 173592 + data_type: SR Legacy + description: Salad dressing, ranch dressing, regular +nutrition_per_100g: + calcium_mg: 28.0 + carbohydrate_g: 5.9 + cholesterol_mg: 26.0 + dietary_fiber_g: 0.0 + energy_kcal: 430 + iron_mg: 0.3 + potassium_mg: 64.0 + protein_g: 1.32 + saturated_fat_g: 6.96 + sodium_mg: 901 + total_fat_g: 44.5 + total_sugars_g: 4.69 + vitamin_d_mcg: 0.1 diff --git a/culinary/source_mappings/usda_fdc_raspberry_2346410.yaml b/culinary/source_mappings/usda_fdc_raspberry_2346410.yaml new file mode 100644 index 0000000..458c477 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_raspberry_2346410.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_raspberry_2346410 +subject: + type: ingredient + id: raspberry +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346410' + url: https://fdc.nal.usda.gov/food-details/2346410/nutrients + title: Raspberries, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346410 + data_type: Foundation + description: Raspberries, raw +nutrition_per_100g: + calcium_mg: 16.41 + carbohydrate_g: 12.904375 + energy_kcal: 51.412425 + iron_mg: 0.4501 + potassium_mg: 155.8 + protein_g: 1.008125 + sodium_mg: 0.0 + total_fat_g: 0.1875 diff --git a/culinary/source_mappings/usda_fdc_raw_broccoli_747447.yaml b/culinary/source_mappings/usda_fdc_raw_broccoli_747447.yaml new file mode 100644 index 0000000..9851415 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_raw_broccoli_747447.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_raw_broccoli_747447 +subject: + type: ingredient + id: raw_broccoli +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '747447' + url: https://fdc.nal.usda.gov/food-details/747447/nutrients + title: Broccoli, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 747447 + data_type: Foundation + description: Broccoli, raw +nutrition_per_100g: + calcium_mg: 46.0 + carbohydrate_g: 6.27 + dietary_fiber_g: 2.4 + energy_kcal: 31.0 + iron_mg: 0.69 + potassium_mg: 303 + protein_g: 2.57 + saturated_fat_g: 0.039 + sodium_mg: 36.0 + total_fat_g: 0.34 diff --git a/culinary/source_mappings/usda_fdc_rice_2512381.yaml b/culinary/source_mappings/usda_fdc_rice_2512381.yaml new file mode 100644 index 0000000..d460413 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_rice_2512381.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_rice_2512381 +subject: + type: ingredient + id: rice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2512381' + url: https://fdc.nal.usda.gov/food-details/2512381/nutrients + title: Rice, white, long grain, unenriched, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2512381 + data_type: Foundation + description: Rice, white, long grain, unenriched, raw +nutrition_per_100g: + calcium_mg: 4.46 + carbohydrate_g: 80.3 + dietary_fiber_g: 0.149 + energy_kcal: 370 + iron_mg: 0.14 + potassium_mg: 82.3 + protein_g: 7.04 + sodium_mg: 0.462 + total_fat_g: 1.03 diff --git a/culinary/source_mappings/usda_fdc_rice_chex_2311632.yaml b/culinary/source_mappings/usda_fdc_rice_chex_2311632.yaml new file mode 100644 index 0000000..982a4ed --- /dev/null +++ b/culinary/source_mappings/usda_fdc_rice_chex_2311632.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: usda_fdc_rice_chex_2311632 +subject: + type: ingredient + id: rice_chex +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2311632' + url: https://fdc.nal.usda.gov/food-details/2311632/nutrients + title: RICE SQUARES TOASTED CEREAL, RICE SQUARES + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2311632 + data_type: Branded + description: RICE SQUARES TOASTED CEREAL, RICE SQUARES + brand_owner: Wal-Mart Stores, Inc. + gtin_upc: 078742183954 +nutrition_per_100g: + calcium_mg: 370.0 + carbohydrate_g: 85.19 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 370.0 + iron_mg: 33.33 + potassium_mg: 111.0 + protein_g: 7.41 + saturated_fat_g: 0.0 + sodium_mg: 704.0 + total_fat_g: 0.0 + total_sugars_g: 7.41 diff --git a/culinary/source_mappings/usda_fdc_rice_cooked_168878.yaml b/culinary/source_mappings/usda_fdc_rice_cooked_168878.yaml new file mode 100644 index 0000000..056d05b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_rice_cooked_168878.yaml @@ -0,0 +1,35 @@ +schema_version: 2 +id: "usda_fdc_rice_cooked_168878" +subject: + type: "ingredient" + id: "rice_cooked" +mapping_type: "nutrition" +status: "reviewed" +source: + source_type: "usda_fdc" + external_id: "168878" + url: "https://fdc.nal.usda.gov/food-details/168878/nutrients" + title: "Rice, white, long-grain, regular, enriched, cooked" + publisher: "USDA Agricultural Research Service" + retrieved_at: "2026-08-12" + reviewed: true + reviewed_at: "2026-08-12" + notes: "FoodData Central data type: SR Legacy." +usda: + fdc_id: 168878 + data_type: "SR Legacy" + description: "Rice, white, long-grain, regular, enriched, cooked" +nutrition_per_100g: + energy_kcal: 130 + protein_g: 2.69 + total_fat_g: 0.28 + carbohydrate_g: 28.17 + dietary_fiber_g: 0.4 + total_sugars_g: 0.05 + calcium_mg: 10 + iron_mg: 1.2 + potassium_mg: 35 + sodium_mg: 1 + vitamin_d_mcg: 0 + saturated_fat_g: 0.077 + cholesterol_mg: 0 diff --git a/culinary/source_mappings/usda_fdc_salt_173468.yaml b/culinary/source_mappings/usda_fdc_salt_173468.yaml new file mode 100644 index 0000000..972d31a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_salt_173468.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_salt_173468 +subject: + type: ingredient + id: salt +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '173468' + url: https://fdc.nal.usda.gov/food-details/173468/nutrients + title: Salt, table + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 173468 + data_type: SR Legacy + description: Salt, table +nutrition_per_100g: + calcium_mg: 24.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 0.0 + iron_mg: 0.33 + potassium_mg: 8.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 38800.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_semisweet_chocolate_167976.yaml b/culinary/source_mappings/usda_fdc_semisweet_chocolate_167976.yaml new file mode 100644 index 0000000..f67e567 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_semisweet_chocolate_167976.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_semisweet_chocolate_167976 +subject: + type: ingredient + id: semisweet_chocolate +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '167976' + url: https://fdc.nal.usda.gov/food-details/167976/nutrients + title: Candies, semisweet chocolate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 167976 + data_type: SR Legacy + description: Candies, semisweet chocolate +nutrition_per_100g: + calcium_mg: 32.0 + carbohydrate_g: 63.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 5.9 + energy_kcal: 480 + iron_mg: 3.13 + potassium_mg: 365 + protein_g: 4.2 + saturated_fat_g: 17.8 + sodium_mg: 11.0 + total_fat_g: 30.0 + total_sugars_g: 54.5 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_sesame_oil_171016.yaml b/culinary/source_mappings/usda_fdc_sesame_oil_171016.yaml new file mode 100644 index 0000000..7b7fb56 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sesame_oil_171016.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_sesame_oil_171016 +subject: + type: ingredient + id: sesame_oil +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171016' + url: https://fdc.nal.usda.gov/food-details/171016/nutrients + title: Oil, sesame, salad or cooking + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171016 + data_type: SR Legacy + description: Oil, sesame, salad or cooking +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 884 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 14.2 + sodium_mg: 0.0 + total_fat_g: 100 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_shaoxing_wine_2440010.yaml b/culinary/source_mappings/usda_fdc_shaoxing_wine_2440010.yaml new file mode 100644 index 0000000..6b35c32 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_shaoxing_wine_2440010.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_shaoxing_wine_2440010 +subject: + type: ingredient + id: shaoxing_wine +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2440010' + url: https://fdc.nal.usda.gov/food-details/2440010/nutrients + title: SHAOHSING RICE COOKING WINE + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2440010 + data_type: Branded + description: SHAOHSING RICE COOKING WINE + brand_owner: Golden International Corp. + gtin_upc: 092516510081 +nutrition_per_100g: + calcium_mg: 2.0 + carbohydrate_g: 0.9 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 80.0 + iron_mg: 0.29 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 496.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_sharp_cheddar_cheese_170899.yaml b/culinary/source_mappings/usda_fdc_sharp_cheddar_cheese_170899.yaml new file mode 100644 index 0000000..d98363e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sharp_cheddar_cheese_170899.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_sharp_cheddar_cheese_170899 +subject: + type: ingredient + id: sharp_cheddar_cheese +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170899' + url: https://fdc.nal.usda.gov/food-details/170899/nutrients + title: Cheese, cheddar, sharp, sliced + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170899 + data_type: SR Legacy + description: Cheese, cheddar, sharp, sliced +nutrition_per_100g: + calcium_mg: 711 + carbohydrate_g: 2.13 + cholesterol_mg: 99.0 + dietary_fiber_g: 0.0 + energy_kcal: 410 + iron_mg: 0.16 + potassium_mg: 76.0 + protein_g: 24.2 + saturated_fat_g: 19.4 + sodium_mg: 644 + total_fat_g: 33.8 + total_sugars_g: 0.27 + vitamin_d_mcg: 1.0 diff --git a/culinary/source_mappings/usda_fdc_shortening_173584.yaml b/culinary/source_mappings/usda_fdc_shortening_173584.yaml new file mode 100644 index 0000000..da3bd54 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_shortening_173584.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_shortening_173584 +subject: + type: ingredient + id: shortening +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '173584' + url: https://fdc.nal.usda.gov/food-details/173584/nutrients + title: Shortening, vegetable, household, composite + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 173584 + data_type: SR Legacy + description: Shortening, vegetable, household, composite +nutrition_per_100g: + calcium_mg: 1.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 884 + iron_mg: 0.07 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 25.0 + sodium_mg: 4.0 + total_fat_g: 100 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_sour_cream_171257.yaml b/culinary/source_mappings/usda_fdc_sour_cream_171257.yaml new file mode 100644 index 0000000..f52a043 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sour_cream_171257.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_sour_cream_171257 +subject: + type: ingredient + id: sour_cream +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171257' + url: https://fdc.nal.usda.gov/food-details/171257/nutrients + title: Cream, sour, cultured + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171257 + data_type: SR Legacy + description: Cream, sour, cultured +nutrition_per_100g: + calcium_mg: 101 + carbohydrate_g: 4.63 + cholesterol_mg: 59.0 + dietary_fiber_g: 0.0 + energy_kcal: 198 + iron_mg: 0.07 + potassium_mg: 125 + protein_g: 2.44 + saturated_fat_g: 10.1 + sodium_mg: 31.0 + total_fat_g: 19.4 + total_sugars_g: 3.41 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_soy_sauce_light_174277.yaml b/culinary/source_mappings/usda_fdc_soy_sauce_light_174277.yaml new file mode 100644 index 0000000..35d6763 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_soy_sauce_light_174277.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_soy_sauce_light_174277 +subject: + type: ingredient + id: soy_sauce_light +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174277' + url: https://fdc.nal.usda.gov/food-details/174277/nutrients + title: Soy sauce made from soy and wheat (shoyu) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174277 + data_type: SR Legacy + description: Soy sauce made from soy and wheat (shoyu) +nutrition_per_100g: + calcium_mg: 33.0 + carbohydrate_g: 4.93 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.8 + energy_kcal: 53.0 + iron_mg: 1.45 + potassium_mg: 435 + protein_g: 8.14 + saturated_fat_g: 0.073 + sodium_mg: 5490.0 + total_fat_g: 0.57 + total_sugars_g: 0.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_soy_sauce_light_low_sodium_172473.yaml b/culinary/source_mappings/usda_fdc_soy_sauce_light_low_sodium_172473.yaml new file mode 100644 index 0000000..51244cc --- /dev/null +++ b/culinary/source_mappings/usda_fdc_soy_sauce_light_low_sodium_172473.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_soy_sauce_light_low_sodium_172473 +subject: + type: ingredient + id: soy_sauce_light_low_sodium +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172473' + url: https://fdc.nal.usda.gov/food-details/172473/nutrients + title: Soy sauce made from soy and wheat (shoyu), low sodium + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172473 + data_type: SR Legacy + description: Soy sauce made from soy and wheat (shoyu), low sodium +nutrition_per_100g: + calcium_mg: 30.0 + carbohydrate_g: 5.59 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.7 + energy_kcal: 57.0 + iron_mg: 1.35 + potassium_mg: 352 + protein_g: 9.05 + saturated_fat_g: 0.035 + sodium_mg: 3600.0 + total_fat_g: 0.3 + total_sugars_g: 0.5 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_soybean_oil_748366.yaml b/culinary/source_mappings/usda_fdc_soybean_oil_748366.yaml new file mode 100644 index 0000000..d5781c1 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_soybean_oil_748366.yaml @@ -0,0 +1,22 @@ +schema_version: 2 +id: usda_fdc_soybean_oil_748366 +subject: + type: ingredient + id: soybean_oil +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '748366' + url: https://fdc.nal.usda.gov/food-details/748366/nutrients + title: Oil, soybean + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 748366 + data_type: Foundation + description: Oil, soybean +nutrition_per_100g: + saturated_fat_g: 14.9 diff --git a/culinary/source_mappings/usda_fdc_sriracha_171186.yaml b/culinary/source_mappings/usda_fdc_sriracha_171186.yaml new file mode 100644 index 0000000..74f8b3e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sriracha_171186.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_sriracha_171186 +subject: + type: ingredient + id: sriracha +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171186' + url: https://fdc.nal.usda.gov/food-details/171186/nutrients + title: Sauce, hot chile, sriracha + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171186 + data_type: SR Legacy + description: Sauce, hot chile, sriracha +nutrition_per_100g: + calcium_mg: 18.0 + carbohydrate_g: 19.2 + dietary_fiber_g: 2.2 + energy_kcal: 93.0 + iron_mg: 1.64 + potassium_mg: 321 + protein_g: 1.93 + sodium_mg: 2120.0 + total_fat_g: 0.93 + total_sugars_g: 15.1 diff --git a/culinary/source_mappings/usda_fdc_sugar_746784.yaml b/culinary/source_mappings/usda_fdc_sugar_746784.yaml new file mode 100644 index 0000000..014151e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sugar_746784.yaml @@ -0,0 +1,29 @@ +schema_version: 2 +id: usda_fdc_sugar_746784 +subject: + type: ingredient + id: sugar +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '746784' + url: https://fdc.nal.usda.gov/food-details/746784/nutrients + title: Sugars, granulated + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 746784 + data_type: Foundation + description: Sugars, granulated +nutrition_per_100g: + calcium_mg: 1.0 + carbohydrate_g: 99.6 + energy_kcal: 385 + iron_mg: 0.05 + potassium_mg: 2.0 + protein_g: 0.0 + sodium_mg: 1.0 + total_fat_g: 0.32 diff --git a/culinary/source_mappings/usda_fdc_sweet_potato_cooked_168484.yaml b/culinary/source_mappings/usda_fdc_sweet_potato_cooked_168484.yaml new file mode 100644 index 0000000..97350d7 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_sweet_potato_cooked_168484.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_sweet_potato_cooked_168484 +subject: + type: ingredient + id: sweet_potato_cooked +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168484' + url: https://fdc.nal.usda.gov/food-details/168484/nutrients + title: Sweet potato, cooked, boiled, without skin + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168484 + data_type: SR Legacy + description: Sweet potato, cooked, boiled, without skin +nutrition_per_100g: + calcium_mg: 27.0 + carbohydrate_g: 17.7 + cholesterol_mg: 0.0 + dietary_fiber_g: 2.5 + energy_kcal: 76.0 + iron_mg: 0.72 + potassium_mg: 230 + protein_g: 1.37 + saturated_fat_g: 0.031 + sodium_mg: 27.0 + total_fat_g: 0.14 + total_sugars_g: 5.74 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_tahini_170189.yaml b/culinary/source_mappings/usda_fdc_tahini_170189.yaml new file mode 100644 index 0000000..e52be4e --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tahini_170189.yaml @@ -0,0 +1,36 @@ +schema_version: 2 +id: usda_fdc_tahini_170189 +subject: + type: ingredient + id: tahini +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170189' + url: https://fdc.nal.usda.gov/food-details/170189/nutrients + title: Seeds, sesame butter, tahini, from roasted and toasted kernels (most common + type) + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170189 + data_type: SR Legacy + description: Seeds, sesame butter, tahini, from roasted and toasted kernels (most + common type) +nutrition_per_100g: + calcium_mg: 426 + carbohydrate_g: 21.2 + cholesterol_mg: 0.0 + dietary_fiber_g: 9.3 + energy_kcal: 595 + iron_mg: 8.95 + potassium_mg: 414 + protein_g: 17.0 + saturated_fat_g: 7.53 + sodium_mg: 115 + total_fat_g: 53.8 + total_sugars_g: 0.49 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_tapioca_starch_2033785.yaml b/culinary/source_mappings/usda_fdc_tapioca_starch_2033785.yaml new file mode 100644 index 0000000..04004ac --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tapioca_starch_2033785.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_tapioca_starch_2033785 +subject: + type: ingredient + id: tapioca_starch +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2033785' + url: https://fdc.nal.usda.gov/food-details/2033785/nutrients + title: TAPIOCA STARCH + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2033785 + data_type: Branded + description: TAPIOCA STARCH + brand_owner: La Venezolana Corp. + gtin_upc: 038225000048 +nutrition_per_100g: + carbohydrate_g: 87.5 + energy_kcal: 375.0 + protein_g: 0.0 + sodium_mg: 300.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_tomato_bouillon_2029306.yaml b/culinary/source_mappings/usda_fdc_tomato_bouillon_2029306.yaml new file mode 100644 index 0000000..c5a72c4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tomato_bouillon_2029306.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_tomato_bouillon_2029306 +subject: + type: ingredient + id: tomato_bouillon +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2029306' + url: https://fdc.nal.usda.gov/food-details/2029306/nutrients + title: TOMATO BOUILLON WITH CHICKEN FLAVOR, TOMATO WITH CHICKEN + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2029306 + data_type: Branded + description: TOMATO BOUILLON WITH CHICKEN FLAVOR, TOMATO WITH CHICKEN + brand_owner: Unilever Bestfoods North America + gtin_upc: 048001711983 +nutrition_per_100g: + carbohydrate_g: 25.0 + energy_kcal: 250.0 + protein_g: 0.0 + sodium_mg: 22750.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_tomato_crushed_in_juice_170051.yaml b/culinary/source_mappings/usda_fdc_tomato_crushed_in_juice_170051.yaml new file mode 100644 index 0000000..911731a --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tomato_crushed_in_juice_170051.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_tomato_crushed_in_juice_170051 +subject: + type: ingredient + id: tomato_crushed_in_juice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170051' + url: https://fdc.nal.usda.gov/food-details/170051/nutrients + title: Tomatoes, red, ripe, canned, packed in tomato juice + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170051 + data_type: SR Legacy + description: Tomatoes, red, ripe, canned, packed in tomato juice +nutrition_per_100g: + calcium_mg: 33.0 + carbohydrate_g: 3.47 + cholesterol_mg: 0.0 + dietary_fiber_g: 1.9 + energy_kcal: 16.0 + iron_mg: 0.57 + potassium_mg: 191 + protein_g: 0.79 + saturated_fat_g: 0.034 + sodium_mg: 115 + total_fat_g: 0.25 + total_sugars_g: 2.55 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_tomato_paste_2685580.yaml b/culinary/source_mappings/usda_fdc_tomato_paste_2685580.yaml new file mode 100644 index 0000000..34f9272 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tomato_paste_2685580.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_tomato_paste_2685580 +subject: + type: ingredient + id: tomato_paste +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2685580' + url: https://fdc.nal.usda.gov/food-details/2685580/nutrients + title: Tomato, paste, canned, without salt added + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2685580 + data_type: Foundation + description: Tomato, paste, canned, without salt added +nutrition_per_100g: + calcium_mg: 36.8 + carbohydrate_g: 20.2 + dietary_fiber_g: 4.7 + energy_kcal: 88.5 + iron_mg: 3.18 + potassium_mg: 972 + protein_g: 4.23 + sodium_mg: 61.2 + total_fat_g: 0.732 diff --git a/culinary/source_mappings/usda_fdc_tomato_puree_2685582.yaml b/culinary/source_mappings/usda_fdc_tomato_puree_2685582.yaml new file mode 100644 index 0000000..f5aae66 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_tomato_puree_2685582.yaml @@ -0,0 +1,30 @@ +schema_version: 2 +id: usda_fdc_tomato_puree_2685582 +subject: + type: ingredient + id: tomato_puree +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2685582' + url: https://fdc.nal.usda.gov/food-details/2685582/nutrients + title: Tomato, puree, canned + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2685582 + data_type: Foundation + description: Tomato, puree, canned +nutrition_per_100g: + calcium_mg: 17.6 + carbohydrate_g: 8.04 + dietary_fiber_g: 1.97 + energy_kcal: 34.8 + iron_mg: 1.24 + potassium_mg: 416 + protein_g: 1.58 + sodium_mg: 29.4 + total_fat_g: 0.265 diff --git a/culinary/source_mappings/usda_fdc_vanilla_extract_173471.yaml b/culinary/source_mappings/usda_fdc_vanilla_extract_173471.yaml new file mode 100644 index 0000000..a71f520 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vanilla_extract_173471.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_vanilla_extract_173471 +subject: + type: ingredient + id: vanilla_extract +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '173471' + url: https://fdc.nal.usda.gov/food-details/173471/nutrients + title: Vanilla extract + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 173471 + data_type: SR Legacy + description: Vanilla extract +nutrition_per_100g: + calcium_mg: 11.0 + carbohydrate_g: 12.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 288 + iron_mg: 0.12 + potassium_mg: 148 + protein_g: 0.06 + saturated_fat_g: 0.01 + sodium_mg: 9.0 + total_fat_g: 0.06 + total_sugars_g: 12.6 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_vinegar_5_172237.yaml b/culinary/source_mappings/usda_fdc_vinegar_5_172237.yaml new file mode 100644 index 0000000..78d9023 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vinegar_5_172237.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_vinegar_5_172237 +subject: + type: ingredient + id: vinegar_5 +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172237' + url: https://fdc.nal.usda.gov/food-details/172237/nutrients + title: Vinegar, distilled + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172237 + data_type: SR Legacy + description: Vinegar, distilled +nutrition_per_100g: + calcium_mg: 6.0 + carbohydrate_g: 0.04 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 18.0 + iron_mg: 0.03 + potassium_mg: 2.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 2.0 + total_fat_g: 0.0 + total_sugars_g: 0.04 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_vinegar_apple_cider_173469.yaml b/culinary/source_mappings/usda_fdc_vinegar_apple_cider_173469.yaml new file mode 100644 index 0000000..793939f --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vinegar_apple_cider_173469.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_vinegar_apple_cider_173469 +subject: + type: ingredient + id: vinegar_apple_cider +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '173469' + url: https://fdc.nal.usda.gov/food-details/173469/nutrients + title: Vinegar, cider + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 173469 + data_type: SR Legacy + description: Vinegar, cider +nutrition_per_100g: + calcium_mg: 7.0 + carbohydrate_g: 0.93 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 21.0 + iron_mg: 0.2 + potassium_mg: 73.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 5.0 + total_fat_g: 0.0 + total_sugars_g: 0.4 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_vinegar_balsamic_172241.yaml b/culinary/source_mappings/usda_fdc_vinegar_balsamic_172241.yaml new file mode 100644 index 0000000..c4e5850 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vinegar_balsamic_172241.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_vinegar_balsamic_172241 +subject: + type: ingredient + id: vinegar_balsamic +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '172241' + url: https://fdc.nal.usda.gov/food-details/172241/nutrients + title: Vinegar, balsamic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 172241 + data_type: SR Legacy + description: Vinegar, balsamic +nutrition_per_100g: + calcium_mg: 27.0 + carbohydrate_g: 17.0 + energy_kcal: 88.0 + iron_mg: 0.72 + potassium_mg: 112 + protein_g: 0.49 + saturated_fat_g: 0.0 + sodium_mg: 23.0 + total_fat_g: 0.0 + total_sugars_g: 15.0 diff --git a/culinary/source_mappings/usda_fdc_vinegar_rice_2085000.yaml b/culinary/source_mappings/usda_fdc_vinegar_rice_2085000.yaml new file mode 100644 index 0000000..5f8fdf9 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vinegar_rice_2085000.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_vinegar_rice_2085000 +subject: + type: ingredient + id: vinegar_rice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2085000' + url: https://fdc.nal.usda.gov/food-details/2085000/nutrients + title: MARUKAN, GENUINE BREWED RICE VINEGAR + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2085000 + data_type: Branded + description: MARUKAN, GENUINE BREWED RICE VINEGAR + brand_owner: Marukan Vinegar (U.S.A.) Inc. + gtin_upc: '070641000042' +nutrition_per_100g: + carbohydrate_g: 0.0 + energy_kcal: 0.0 + protein_g: 0.0 + sodium_mg: 0.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_vodka_174818.yaml b/culinary/source_mappings/usda_fdc_vodka_174818.yaml new file mode 100644 index 0000000..150733b --- /dev/null +++ b/culinary/source_mappings/usda_fdc_vodka_174818.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_vodka_174818 +subject: + type: ingredient + id: vodka +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174818' + url: https://fdc.nal.usda.gov/food-details/174818/nutrients + title: Alcoholic beverage, distilled, vodka, 80 proof + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174818 + data_type: SR Legacy + description: Alcoholic beverage, distilled, vodka, 80 proof +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 231 + iron_mg: 0.01 + potassium_mg: 1.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 1.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_walnut_2346394.yaml b/culinary/source_mappings/usda_fdc_walnut_2346394.yaml new file mode 100644 index 0000000..3085f7c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_walnut_2346394.yaml @@ -0,0 +1,31 @@ +schema_version: 2 +id: usda_fdc_walnut_2346394 +subject: + type: ingredient + id: walnut +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2346394' + url: https://fdc.nal.usda.gov/food-details/2346394/nutrients + title: Nuts, walnuts, English, halves, raw + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2346394 + data_type: Foundation + description: Nuts, walnuts, English, halves, raw +nutrition_per_100g: + calcium_mg: 88.3 + carbohydrate_g: 10.9 + dietary_fiber_g: 5.21 + energy_kcal: 679 + iron_mg: 2.24 + potassium_mg: 424 + protein_g: 14.6 + saturated_fat_g: 6.05 + sodium_mg: 0.0 + total_fat_g: 69.7 diff --git a/culinary/source_mappings/usda_fdc_water_ice_174158.yaml b/culinary/source_mappings/usda_fdc_water_ice_174158.yaml new file mode 100644 index 0000000..b9e91f4 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_water_ice_174158.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_water_ice_174158 +subject: + type: ingredient + id: water_ice +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '174158' + url: https://fdc.nal.usda.gov/food-details/174158/nutrients + title: Water, bottled, generic + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 174158 + data_type: SR Legacy + description: Water, bottled, generic +nutrition_per_100g: + calcium_mg: 10.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 0.0 + iron_mg: 0.0 + potassium_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 2.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_wheat_gluten_70_80_168147.yaml b/culinary/source_mappings/usda_fdc_wheat_gluten_70_80_168147.yaml new file mode 100644 index 0000000..dd1a6d1 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_wheat_gluten_70_80_168147.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_wheat_gluten_70_80_168147 +subject: + type: ingredient + id: wheat_gluten_70_80 +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '168147' + url: https://fdc.nal.usda.gov/food-details/168147/nutrients + title: Vital wheat gluten + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 168147 + data_type: SR Legacy + description: Vital wheat gluten +nutrition_per_100g: + calcium_mg: 142 + carbohydrate_g: 13.8 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.6 + energy_kcal: 370 + iron_mg: 5.2 + potassium_mg: 100 + protein_g: 75.2 + saturated_fat_g: 0.272 + sodium_mg: 29.0 + total_fat_g: 1.85 + total_sugars_g: 0.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_white_chocolate_167571.yaml b/culinary/source_mappings/usda_fdc_white_chocolate_167571.yaml new file mode 100644 index 0000000..130769d --- /dev/null +++ b/culinary/source_mappings/usda_fdc_white_chocolate_167571.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_white_chocolate_167571 +subject: + type: ingredient + id: white_chocolate +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '167571' + url: https://fdc.nal.usda.gov/food-details/167571/nutrients + title: Candies, white chocolate + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 167571 + data_type: SR Legacy + description: Candies, white chocolate +nutrition_per_100g: + calcium_mg: 199 + carbohydrate_g: 59.2 + cholesterol_mg: 21.0 + dietary_fiber_g: 0.2 + energy_kcal: 539 + iron_mg: 0.24 + potassium_mg: 286 + protein_g: 5.87 + saturated_fat_g: 19.4 + sodium_mg: 90.0 + total_fat_g: 32.1 + total_sugars_g: 59.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_white_pepper_170933.yaml b/culinary/source_mappings/usda_fdc_white_pepper_170933.yaml new file mode 100644 index 0000000..f66378c --- /dev/null +++ b/culinary/source_mappings/usda_fdc_white_pepper_170933.yaml @@ -0,0 +1,33 @@ +schema_version: 2 +id: usda_fdc_white_pepper_170933 +subject: + type: ingredient + id: white_pepper +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '170933' + url: https://fdc.nal.usda.gov/food-details/170933/nutrients + title: Spices, pepper, white + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 170933 + data_type: SR Legacy + description: Spices, pepper, white +nutrition_per_100g: + calcium_mg: 265 + carbohydrate_g: 68.6 + cholesterol_mg: 0.0 + dietary_fiber_g: 26.2 + energy_kcal: 296 + iron_mg: 14.3 + potassium_mg: 73.0 + protein_g: 10.4 + saturated_fat_g: 0.626 + sodium_mg: 5.0 + total_fat_g: 2.12 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_worschestershire_sauce_171610.yaml b/culinary/source_mappings/usda_fdc_worschestershire_sauce_171610.yaml new file mode 100644 index 0000000..b627e42 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_worschestershire_sauce_171610.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_worschestershire_sauce_171610 +subject: + type: ingredient + id: worschestershire_sauce +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '171610' + url: https://fdc.nal.usda.gov/food-details/171610/nutrients + title: Sauce, worcestershire + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 171610 + data_type: SR Legacy + description: Sauce, worcestershire +nutrition_per_100g: + calcium_mg: 107 + carbohydrate_g: 19.2 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 77.0 + iron_mg: 5.3 + potassium_mg: 800 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 1300.0 + total_fat_g: 0.0 + total_sugars_g: 10.0 + vitamin_d_mcg: 0.0 diff --git a/culinary/source_mappings/usda_fdc_xanthan_gum_1991838.yaml b/culinary/source_mappings/usda_fdc_xanthan_gum_1991838.yaml new file mode 100644 index 0000000..3a49425 --- /dev/null +++ b/culinary/source_mappings/usda_fdc_xanthan_gum_1991838.yaml @@ -0,0 +1,28 @@ +schema_version: 2 +id: usda_fdc_xanthan_gum_1991838 +subject: + type: ingredient + id: xanthan_gum +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '1991838' + url: https://fdc.nal.usda.gov/food-details/1991838/nutrients + title: XANTHAN GUM + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 1991838 + data_type: Branded + description: XANTHAN GUM + brand_owner: Now Health Group Inc. + gtin_upc: '733739061997' +nutrition_per_100g: + carbohydrate_g: 125.0 + energy_kcal: 625.0 + protein_g: 0.0 + sodium_mg: 3125.0 + total_fat_g: 0.0 diff --git a/culinary/source_mappings/usda_fdc_yogurt_2259793.yaml b/culinary/source_mappings/usda_fdc_yogurt_2259793.yaml new file mode 100644 index 0000000..877a0ba --- /dev/null +++ b/culinary/source_mappings/usda_fdc_yogurt_2259793.yaml @@ -0,0 +1,32 @@ +schema_version: 2 +id: usda_fdc_yogurt_2259793 +subject: + type: ingredient + id: yogurt +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2259793' + url: https://fdc.nal.usda.gov/food-details/2259793/nutrients + title: Yogurt, plain, whole milk + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2259793 + data_type: Foundation + description: Yogurt, plain, whole milk +nutrition_per_100g: + calcium_mg: 127 + carbohydrate_g: 5.57 + cholesterol_mg: 14.2 + energy_kcal: 77.3 + iron_mg: 0.0 + potassium_mg: 164 + protein_g: 3.82 + saturated_fat_g: 2.32 + sodium_mg: 41.8 + total_fat_g: 4.48 + vitamin_d_mcg: 0.778 diff --git a/culinary/source_mappings/usda_fdc_zaatar_2072928.yaml b/culinary/source_mappings/usda_fdc_zaatar_2072928.yaml new file mode 100644 index 0000000..d1001cc --- /dev/null +++ b/culinary/source_mappings/usda_fdc_zaatar_2072928.yaml @@ -0,0 +1,34 @@ +schema_version: 2 +id: usda_fdc_zaatar_2072928 +subject: + type: ingredient + id: zaatar +mapping_type: nutrition +status: reviewed +source: + source_type: usda_fdc + external_id: '2072928' + url: https://fdc.nal.usda.gov/food-details/2072928/nutrients + title: LEBANON ZAATAR THYME SEASONING + publisher: USDA Agricultural Research Service + retrieved_at: '2026-08-11' + reviewed: true + reviewed_at: '2026-08-11' +usda: + fdc_id: 2072928 + data_type: Branded + description: LEBANON ZAATAR THYME SEASONING + brand_owner: Salloum Bros Industry & Trading sarl + gtin_upc: '5281020050021' +nutrition_per_100g: + calcium_mg: 0.0 + carbohydrate_g: 0.0 + cholesterol_mg: 0.0 + dietary_fiber_g: 0.0 + energy_kcal: 0.0 + iron_mg: 0.0 + protein_g: 0.0 + saturated_fat_g: 0.0 + sodium_mg: 0.0 + total_fat_g: 0.0 + total_sugars_g: 0.0 diff --git a/culinary/suppliers/sams_club.yaml b/culinary/suppliers/sams_club.yaml new file mode 100644 index 0000000..aa77a3d --- /dev/null +++ b/culinary/suppliers/sams_club.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: sams_club +name: Sam's Club +status: active +website: https://www.samsclub.com/ +notes: +- Receipt observations may be club-specific. diff --git a/culinary/suppliers/walmart.yaml b/culinary/suppliers/walmart.yaml new file mode 100644 index 0000000..dca8248 --- /dev/null +++ b/culinary/suppliers/walmart.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: walmart +name: Walmart +status: active +website: https://www.walmart.com/ +notes: +- Receipt observations may be store-specific. diff --git a/culinary/units/celsius.yaml b/culinary/units/celsius.yaml new file mode 100644 index 0000000..64f75b9 --- /dev/null +++ b/culinary/units/celsius.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: celsius +name: degree Celsius +symbol: °C +aliases: [C, degree_celsius] +dimension: temperature +system: metric diff --git a/culinary/units/centimeter.yaml b/culinary/units/centimeter.yaml new file mode 100644 index 0000000..f6b55e6 --- /dev/null +++ b/culinary/units/centimeter.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: centimeter +name: centimeter +symbol: cm +aliases: [centimeters] +dimension: length +system: metric +base_conversion: + base_unit_id: millimeter + factor: 10 diff --git a/culinary/units/cup_metric.yaml b/culinary/units/cup_metric.yaml new file mode 100644 index 0000000..4c748ef --- /dev/null +++ b/culinary/units/cup_metric.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: cup_metric +name: metric cup +symbol: cup metric +aliases: [metric_cup] +dimension: volume +system: metric +base_conversion: + base_unit_id: milliliter + factor: 250 diff --git a/culinary/units/cup_us.yaml b/culinary/units/cup_us.yaml new file mode 100644 index 0000000..5fb115e --- /dev/null +++ b/culinary/units/cup_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: cup_us +name: US legal cup +symbol: cup +aliases: [cups] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 240 diff --git a/culinary/units/dozen.yaml b/culinary/units/dozen.yaml new file mode 100644 index 0000000..2dc57c0 --- /dev/null +++ b/culinary/units/dozen.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: dozen +name: dozen +symbol: doz +aliases: [dozens] +dimension: count +system: universal +base_conversion: + base_unit_id: each + factor: 12 diff --git a/culinary/units/each.yaml b/culinary/units/each.yaml new file mode 100644 index 0000000..148a134 --- /dev/null +++ b/culinary/units/each.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: each +name: each +symbol: ea +aliases: [count] +dimension: count +system: universal diff --git a/culinary/units/fahrenheit.yaml b/culinary/units/fahrenheit.yaml new file mode 100644 index 0000000..751d96c --- /dev/null +++ b/culinary/units/fahrenheit.yaml @@ -0,0 +1,11 @@ +schema_version: 2 +id: fahrenheit +name: degree Fahrenheit +symbol: °F +aliases: [F, degree_fahrenheit] +dimension: temperature +system: us_customary +base_conversion: + base_unit_id: celsius + factor: 0.5555555555555556 + offset: -17.77777777777778 diff --git a/culinary/units/fluid_ounce_us.yaml b/culinary/units/fluid_ounce_us.yaml new file mode 100644 index 0000000..0d63c75 --- /dev/null +++ b/culinary/units/fluid_ounce_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: fluid_ounce_us +name: US fluid ounce +symbol: fl oz +aliases: [fluid_ounce, fluid_ounces] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 29.5735295625 diff --git a/culinary/units/gallon_us.yaml b/culinary/units/gallon_us.yaml new file mode 100644 index 0000000..e59b74c --- /dev/null +++ b/culinary/units/gallon_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: gallon_us +name: US liquid gallon +symbol: gal +aliases: [gallon, gallons] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 3785.411784 diff --git a/culinary/units/gram.yaml b/culinary/units/gram.yaml new file mode 100644 index 0000000..bf4e3cf --- /dev/null +++ b/culinary/units/gram.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: gram +name: gram +symbol: g +aliases: [grams] +dimension: mass +system: metric diff --git a/culinary/units/hour.yaml b/culinary/units/hour.yaml new file mode 100644 index 0000000..15d923f --- /dev/null +++ b/culinary/units/hour.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: hour +name: hour +symbol: h +aliases: [hours, hr] +dimension: time +system: universal +base_conversion: + base_unit_id: minute + factor: 60 diff --git a/culinary/units/inch.yaml b/culinary/units/inch.yaml new file mode 100644 index 0000000..5accc91 --- /dev/null +++ b/culinary/units/inch.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: inch +name: inch +symbol: in +aliases: [inches] +dimension: length +system: us_customary +base_conversion: + base_unit_id: millimeter + factor: 25.4 diff --git a/culinary/units/kelvin.yaml b/culinary/units/kelvin.yaml new file mode 100644 index 0000000..8ef39b4 --- /dev/null +++ b/culinary/units/kelvin.yaml @@ -0,0 +1,11 @@ +schema_version: 2 +id: kelvin +name: kelvin +symbol: K +aliases: [degrees_kelvin] +dimension: temperature +system: metric +base_conversion: + base_unit_id: celsius + factor: 1 + offset: -273.15 diff --git a/culinary/units/kilogram.yaml b/culinary/units/kilogram.yaml new file mode 100644 index 0000000..a7955e8 --- /dev/null +++ b/culinary/units/kilogram.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: kilogram +name: kilogram +symbol: kg +aliases: [kilograms] +dimension: mass +system: metric +base_conversion: + base_unit_id: gram + factor: 1000 diff --git a/culinary/units/liter.yaml b/culinary/units/liter.yaml new file mode 100644 index 0000000..ef66113 --- /dev/null +++ b/culinary/units/liter.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: liter +name: liter +symbol: L +aliases: [liters, litre, litres] +dimension: volume +system: metric +base_conversion: + base_unit_id: milliliter + factor: 1000 diff --git a/culinary/units/meter.yaml b/culinary/units/meter.yaml new file mode 100644 index 0000000..1e71a16 --- /dev/null +++ b/culinary/units/meter.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: meter +name: meter +symbol: m +aliases: [meters] +dimension: length +system: metric +base_conversion: + base_unit_id: millimeter + factor: 1000 diff --git a/culinary/units/microgram.yaml b/culinary/units/microgram.yaml new file mode 100644 index 0000000..bec37fd --- /dev/null +++ b/culinary/units/microgram.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: microgram +name: microgram +symbol: µg +aliases: [micrograms, mcg] +dimension: mass +system: metric +base_conversion: + base_unit_id: gram + factor: 0.000001 diff --git a/culinary/units/milligram.yaml b/culinary/units/milligram.yaml new file mode 100644 index 0000000..624d789 --- /dev/null +++ b/culinary/units/milligram.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: milligram +name: milligram +symbol: mg +aliases: [milligrams] +dimension: mass +system: metric +base_conversion: + base_unit_id: gram + factor: 0.001 diff --git a/culinary/units/milliliter.yaml b/culinary/units/milliliter.yaml new file mode 100644 index 0000000..8a3eaf7 --- /dev/null +++ b/culinary/units/milliliter.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: milliliter +name: milliliter +symbol: mL +aliases: [milliliters, ml] +dimension: volume +system: metric diff --git a/culinary/units/millimeter.yaml b/culinary/units/millimeter.yaml new file mode 100644 index 0000000..d61aec9 --- /dev/null +++ b/culinary/units/millimeter.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: millimeter +name: millimeter +symbol: mm +aliases: [millimeters] +dimension: length +system: metric diff --git a/culinary/units/minute.yaml b/culinary/units/minute.yaml new file mode 100644 index 0000000..7006255 --- /dev/null +++ b/culinary/units/minute.yaml @@ -0,0 +1,7 @@ +schema_version: 2 +id: minute +name: minute +symbol: min +aliases: [minutes] +dimension: time +system: universal diff --git a/culinary/units/ounce_mass.yaml b/culinary/units/ounce_mass.yaml new file mode 100644 index 0000000..9054dd4 --- /dev/null +++ b/culinary/units/ounce_mass.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: ounce_mass +name: ounce +symbol: oz +aliases: [ounces, oz_weight] +dimension: mass +system: us_customary +base_conversion: + base_unit_id: gram + factor: 28.349523125 diff --git a/culinary/units/pint_us.yaml b/culinary/units/pint_us.yaml new file mode 100644 index 0000000..432cd15 --- /dev/null +++ b/culinary/units/pint_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: pint_us +name: US liquid pint +symbol: pt +aliases: [pint, pints] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 473.176473 diff --git a/culinary/units/pound.yaml b/culinary/units/pound.yaml new file mode 100644 index 0000000..31b18e2 --- /dev/null +++ b/culinary/units/pound.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: pound +name: pound +symbol: lb +aliases: [pounds, lbs] +dimension: mass +system: us_customary +base_conversion: + base_unit_id: gram + factor: 453.59237 diff --git a/culinary/units/quart_us.yaml b/culinary/units/quart_us.yaml new file mode 100644 index 0000000..a1ed15e --- /dev/null +++ b/culinary/units/quart_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: quart_us +name: US liquid quart +symbol: qt +aliases: [quart, quarts] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 946.352946 diff --git a/culinary/units/second.yaml b/culinary/units/second.yaml new file mode 100644 index 0000000..95616da --- /dev/null +++ b/culinary/units/second.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: second +name: second +symbol: s +aliases: [seconds, sec] +dimension: time +system: universal +base_conversion: + base_unit_id: minute + factor: 0.016666666666666666 diff --git a/culinary/units/tablespoon_metric.yaml b/culinary/units/tablespoon_metric.yaml new file mode 100644 index 0000000..8a87ad7 --- /dev/null +++ b/culinary/units/tablespoon_metric.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: tablespoon_metric +name: metric tablespoon +symbol: tbsp metric +aliases: [metric_tablespoon] +dimension: volume +system: metric +base_conversion: + base_unit_id: milliliter + factor: 15 diff --git a/culinary/units/tablespoon_us.yaml b/culinary/units/tablespoon_us.yaml new file mode 100644 index 0000000..49c36ec --- /dev/null +++ b/culinary/units/tablespoon_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: tablespoon_us +name: US tablespoon +symbol: tbsp +aliases: [tablespoon, tablespoons] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 14.78676478125 diff --git a/culinary/units/teaspoon_metric.yaml b/culinary/units/teaspoon_metric.yaml new file mode 100644 index 0000000..b488b08 --- /dev/null +++ b/culinary/units/teaspoon_metric.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: teaspoon_metric +name: metric teaspoon +symbol: tsp metric +aliases: [metric_teaspoon] +dimension: volume +system: metric +base_conversion: + base_unit_id: milliliter + factor: 5 diff --git a/culinary/units/teaspoon_us.yaml b/culinary/units/teaspoon_us.yaml new file mode 100644 index 0000000..5946d19 --- /dev/null +++ b/culinary/units/teaspoon_us.yaml @@ -0,0 +1,10 @@ +schema_version: 2 +id: teaspoon_us +name: US teaspoon +symbol: tsp +aliases: [teaspoon, teaspoons] +dimension: volume +system: us_customary +base_conversion: + base_unit_id: milliliter + factor: 4.92892159375 diff --git a/docs/culinary-data-model.md b/docs/culinary-data-model.md new file mode 100644 index 0000000..21c1ad5 --- /dev/null +++ b/docs/culinary-data-model.md @@ -0,0 +1,136 @@ +# Culinary data model + +## Direction + +Schema version 2 is a vendor-neutral culinary domain model designed to map +cleanly to relational tables while remaining portable, reviewable YAML. Astro is +a presentation consumer only. It must not become the authority for quantities, +conversions, nutrition, allergens, purchasing, or calculated values. + +`schema_version` describes a document's data contract. A recipe's `revision` +independently describes changes to that recipe. Names used for search or display +belong in ingredient `aliases`; canonical references always use stable entity +IDs. + +## Canonical and derived boundaries + +Canonical records live under `culinary/`. They contain authored or observed +facts: recipes, ingredients, measurements, provenance, suppliers, packages, +and price observations. Projections may later be generated for another +application or database, but they are never canonical. + +Derived recipe records contain reproducible nutrition, allergen rollups, and +costs. They identify the recipe revision, calculation version, calculation +time, and an input fingerprint. Derived values are disposable and must never +be copied back into canonical source fields as though they were observations. + +## Entity model + +The schema set in `container/schemas/v2/` defines these prospective relational +entities: + +| Entity | Main relationships | +| --- | --- | +| Recipe | revision; components; ordered lines and steps; ingredients or sub-recipes | +| Ingredient | aliases; sourced density/measure observations; nutrition/allergen mappings | +| Unit | dimension and conversion to a base unit within that dimension | +| Prep action | optional default edible-yield factor | +| Source mapping | ingredient, purchasing-item, or recipe nutrition/allergen evidence | +| Supplier | purchasing items | +| Purchasing item | ingredient, supplier, package, dated prices, product mappings | +| Equipment | referenced by recipe steps | +| Collection | ordered recipe references for menus or collections | +| Derived recipe | calculated cost, nutrition, allergens, completeness, and warnings | + +Recipe components, component lines, and preparation steps are embedded because +they form a recipe revision aggregate and are edited together. Reusable facts +remain independent records referenced by stable IDs. + +Equipment is a reusable, vendor-neutral entity. A recipe may declare equipment +needed anywhere in the process with `equipment_ids`; individual steps may add +their own `equipment_ids` to show when each item is used. The displayed setup +list is the union of both sets, without duplicating equipment definitions in +recipe files. + +Allergen mappings and suppliers are optional capabilities. A purchasing item +may record an exact product, package, and price without identifying a formal +supplier. Recipes and ingredients never require allergen or supplier records. + +## Quantities, scaling, and yield + +An `amount` is always a numeric quantity plus a normalized `unit_id`. A recipe +declares amount, percentage, or hybrid scaling. Hybrid records include both +canonical amounts and percentages; calculation tooling must verify agreement +against the declared basis. + +Recipe yield is explicit and identifies whether it is measured, estimated, or +theoretical. A finished measured yield is preferred for per-100-gram nutrition +and costing. Serving count and serving size are separate optional facts. + +Prep actions may override their default `yield_factor` on a recipe line. The +recipe amount is the usable quantity entering the formula; the factor determines +the larger as-purchased quantity required for costing. For example, 100 grams of +usable onion at an 80% prep yield requires purchasing 125 grams. Cooking loss +that affects the entire recipe belongs in recipe yield, not an ingredient +purchase factor. + +In operational recipe management, the finished recipe yield is +authoritative for costing, portioning, and per-weight nutrition. Record the +actual finished weight after cooking and handling; this single measurement +captures evaporation, absorption, rendering, and material left on equipment. +Ingredient-specific trimming, peeling, and draining remain explicit prep-action +yield factors. Cooking water deliberately added to rice is a normal recipe input. + +## Units, density, and household measures + +Universal unit conversion applies only within a dimension: mass-to-mass, +volume-to-volume, time-to-time, and so on. Volume-to-mass conversion requires +ingredient-specific evidence. + +For normalized units, `base_conversion` means: +`base value = source value × factor + offset`. Mass resolves to grams, volume +to milliliters, time to minutes, count to each, length to millimeters, and +temperature to Celsius. US volume units are identified explicitly; an +unqualified international "cup" is not assumed. + +An ingredient density measurement stores a mass, a volume, physical state, +temperature when relevant, and provenance. This is intentionally represented +as an observed ratio rather than a context-free `density` scalar. A rounded +culinary approximation can coexist with a laboratory measurement without +pretending they have equal precision. + +Ingredient `measure_conversions` cover non-density measures such as one clove, +one packed cup, or one drained can. Preparation state belongs on the conversion +because sifted, packed, chopped, and whole materials may have different bulk +measures. + +## USDA FoodData Central + +USDA FoodData Central mappings are provenance records, not attributes that +define an ingredient. A reviewed mapping records the FDC ID, FoodData Central +data type, exact description, retrieval date, and the normalized nutrient +values imported from that record. Candidate mappings remain distinguishable +from reviewed mappings. + +Prefer Foundation Foods for suitable basic foods, followed by SR Legacy or +FNDDS when they are a better semantic match. Use a Branded record only for the +specific purchasing item or when the canonical ingredient intentionally means +that exact product. Prepared components should normally derive nutrition from +their recipes instead of being forced onto an approximate FDC record. + +The USDA API key must never be stored in the repository. Future import tooling +should propose candidates, cache source payloads or normalized facts with their +retrieval dates, and require review before a mapping becomes authoritative. + +## Canonical status + +SQLite is the canonical application store. The files in `culinary/` are a +portable import/export dataset and initial seed, not a second writable source of +truth. Recipes without authored instructions contain one explicit TODO step and +remain drafts. Formula-only conversions use a nominal 100 g basis and a +theoretical yield until those values are replaced by observed production data. + +Astro reads a generated, read-only SQLite projection and produces static recipe +pages. Interactive calculators are small Preact islands supplied with resolved, +typed recipe data. Astro and Preact remain presentation consumers; culinary +calculations and editing originate in the database and shared calculation tools. diff --git a/docs/local-application.md b/docs/local-application.md new file mode 100644 index 0000000..105f14c --- /dev/null +++ b/docs/local-application.md @@ -0,0 +1,33 @@ +# Local recipe application + +The local application uses SQLite as its canonical data store. YAML remains a +portable import/export format, but normal application saves do not modify it. +Derived nutrition and cost are still calculated rather than stored. + +Create the initial database from the current portable dataset with Node 22 or +newer, then run the site and application: + +```sh +npm run db:reset +npm run dev:site +npm run dev:app +``` + +`npm run site:project` writes `generated/site-projection.json`. Site development, +checks, and builds run it automatically. Successful application edits refresh +the same file, allowing the local Astro site to hot-reload database changes while +remaining read-only. + +The database is written to `var/recipe-book.sqlite` and is intentionally ignored +by Git. Numbered SQL migrations in `migrations/` define the durable relational +schema. Run `npm run db:migrate` to upgrade an existing database without +re-importing or deleting its data. Writable application connections also apply +pending migrations automatically. The `/app/` dashboard is available in +development mode. Recipe metadata and yield edits are transactional, increment +the recipe revision, retain the previous state in `recipe_revisions`, and reject +saves from stale browser tabs. Portable exports are a separate backup and +interchange workflow, not part of normal editing. + +`npm run db:sync` is a compatibility alias for the safe migration command. +`npm run db:import:yaml` (or `db:reset`) replaces the database from YAML and is +only intended for initial setup or an explicit restore. diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..5939fdb --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: recipe-book + labels: + app.kubernetes.io/name: recipe-book +spec: + replicas: 2 + revisionHistoryLimit: 5 + progressDeadlineSeconds: 180 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + selector: + matchLabels: + app.kubernetes.io/name: recipe-book + template: + metadata: + labels: + app.kubernetes.io/name: recipe-book + spec: + imagePullSecrets: + - name: gitea-registry + containers: + - name: recipe-book + image: git.uuard.com/nicholas/recipe-book + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 80 + protocol: TCP + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 6 + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 + resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 100m + memory: 128Mi + securityContext: + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..caacd86 --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: recipe-book + labels: + app.kubernetes.io/name: recipe-book +spec: + ingressClassName: traefik + rules: + - host: recipes.uuard.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: recipe-book + port: + name: http diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 0000000..4eb1d37 --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: nicholas +resources: + - deployment.yaml + - service.yaml + - ingress.yaml +images: + - name: git.uuard.com/nicholas/recipe-book + newTag: 7c17e3047560967dd58f8f7b8f0dd7387ba46aa5 diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..61afba1 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: recipe-book + labels: + app.kubernetes.io/name: recipe-book +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: recipe-book + ports: + - name: http + port: 80 + targetPort: http + protocol: TCP diff --git a/migrations/001_initial.sql b/migrations/001_initial.sql new file mode 100644 index 0000000..867025b --- /dev/null +++ b/migrations/001_initial.sql @@ -0,0 +1,169 @@ +PRAGMA foreign_keys = ON; + +CREATE TABLE IF NOT EXISTS schema_migrations ( + version INTEGER PRIMARY KEY, + name TEXT NOT NULL, + applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE units ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + symbol TEXT NOT NULL, + dimension TEXT NOT NULL, + system TEXT NOT NULL, + base_unit_id TEXT REFERENCES units(id), + factor REAL, + offset REAL +); + +CREATE TABLE ingredients ( + id TEXT PRIMARY KEY, + schema_version INTEGER NOT NULL, + name TEXT NOT NULL, + status TEXT NOT NULL, + categories_json TEXT NOT NULL DEFAULT '[]' +); + +CREATE TABLE ingredient_aliases ( + ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE, + name TEXT NOT NULL, + kind TEXT, + PRIMARY KEY (ingredient_id, name) +); + +CREATE TABLE equipment ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + category TEXT, + notes TEXT +); + +CREATE TABLE prep_actions ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + action_type TEXT NOT NULL, + default_yield_factor REAL CHECK(default_yield_factor > 0 AND default_yield_factor <= 1), + notes TEXT +); + +CREATE TABLE recipes ( + id TEXT PRIMARY KEY, + schema_version INTEGER NOT NULL, + revision INTEGER NOT NULL, + status TEXT NOT NULL, + title TEXT NOT NULL, + summary TEXT, + categories_json TEXT NOT NULL DEFAULT '[]', + tags_json TEXT NOT NULL DEFAULT '[]', + yield_quantity REAL NOT NULL, + yield_unit_id TEXT NOT NULL REFERENCES units(id), + yield_servings REAL, + yield_basis TEXT, + scaling_mode TEXT, + scaling_basis_id TEXT, + scaling_basis_quantity REAL, + scaling_basis_unit_id TEXT REFERENCES units(id), + notes_json TEXT NOT NULL DEFAULT '[]' +); + +CREATE TABLE recipe_components ( + recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, + id TEXT NOT NULL, + position INTEGER NOT NULL, + name TEXT NOT NULL, + notes_json TEXT NOT NULL DEFAULT '[]', + PRIMARY KEY (recipe_id, id) +); + +CREATE TABLE recipe_items ( + recipe_id TEXT NOT NULL, + component_id TEXT NOT NULL, + id TEXT NOT NULL, + position INTEGER NOT NULL, + ingredient_id TEXT REFERENCES ingredients(id), + subrecipe_id TEXT REFERENCES recipes(id), + subrecipe_revision INTEGER, + quantity REAL NOT NULL, + unit_id TEXT NOT NULL REFERENCES units(id), + percentage REAL, + basis_member INTEGER NOT NULL DEFAULT 0, + optional INTEGER NOT NULL DEFAULT 0, + notes TEXT, + PRIMARY KEY (recipe_id, id), + FOREIGN KEY (recipe_id, component_id) REFERENCES recipe_components(recipe_id, id) ON DELETE CASCADE, + CHECK ((ingredient_id IS NOT NULL) <> (subrecipe_id IS NOT NULL)) +); + +CREATE TABLE item_prep_actions ( + recipe_id TEXT NOT NULL, + item_id TEXT NOT NULL, + position INTEGER NOT NULL, + action_id TEXT NOT NULL REFERENCES prep_actions(id), + yield_factor REAL CHECK(yield_factor > 0 AND yield_factor <= 1), + notes TEXT, + PRIMARY KEY (recipe_id, item_id, position), + FOREIGN KEY (recipe_id, item_id) REFERENCES recipe_items(recipe_id, id) ON DELETE CASCADE +); + +CREATE TABLE recipe_steps ( + recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, + id TEXT NOT NULL, + position INTEGER NOT NULL, + instruction TEXT NOT NULL, + critical_control_point INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY (recipe_id, id), + UNIQUE (recipe_id, position) +); + +CREATE TABLE recipe_equipment ( + recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, + equipment_id TEXT NOT NULL REFERENCES equipment(id), + PRIMARY KEY (recipe_id, equipment_id) +); + +CREATE TABLE step_equipment ( + recipe_id TEXT NOT NULL, + step_id TEXT NOT NULL, + equipment_id TEXT NOT NULL REFERENCES equipment(id), + PRIMARY KEY (recipe_id, step_id, equipment_id), + FOREIGN KEY (recipe_id, step_id) REFERENCES recipe_steps(recipe_id, id) ON DELETE CASCADE +); + +CREATE TABLE purchase_items ( + id TEXT PRIMARY KEY, + ingredient_id TEXT NOT NULL REFERENCES ingredients(id), + name TEXT NOT NULL, + brand TEXT, + supplier_id TEXT, + supplier_sku TEXT, + status TEXT NOT NULL, + package_quantity REAL NOT NULL, + package_unit_id TEXT NOT NULL REFERENCES units(id), + units_per_case INTEGER NOT NULL DEFAULT 1, + usable_yield_factor REAL NOT NULL DEFAULT 1 +); + +CREATE TABLE price_observations ( + purchase_item_id TEXT NOT NULL REFERENCES purchase_items(id) ON DELETE CASCADE, + effective_at TEXT NOT NULL, + currency TEXT NOT NULL, + amount REAL NOT NULL, + source_json TEXT NOT NULL, + PRIMARY KEY (purchase_item_id, effective_at, currency) +); + +CREATE TABLE source_mappings ( + id TEXT PRIMARY KEY, + subject_type TEXT NOT NULL, + subject_id TEXT NOT NULL, + mapping_type TEXT NOT NULL, + status TEXT NOT NULL, + source_json TEXT NOT NULL, + nutrition_json TEXT +); + +CREATE INDEX recipe_items_ingredient_idx ON recipe_items(ingredient_id); +CREATE INDEX recipe_items_subrecipe_idx ON recipe_items(subrecipe_id); +CREATE INDEX purchase_items_ingredient_idx ON purchase_items(ingredient_id); +CREATE INDEX source_mappings_subject_idx ON source_mappings(subject_type, subject_id); diff --git a/migrations/002_recipe_editing.sql b/migrations/002_recipe_editing.sql new file mode 100644 index 0000000..fdcf062 --- /dev/null +++ b/migrations/002_recipe_editing.sql @@ -0,0 +1,10 @@ +ALTER TABLE recipes ADD COLUMN source_json TEXT NOT NULL DEFAULT '{}'; + +CREATE TABLE recipe_revisions ( + recipe_id TEXT NOT NULL, + revision INTEGER NOT NULL, + saved_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + change_summary TEXT NOT NULL, + snapshot_json TEXT NOT NULL, + PRIMARY KEY (recipe_id, revision) +); diff --git a/migrations/003_ingredient_workspace.sql b/migrations/003_ingredient_workspace.sql new file mode 100644 index 0000000..b16e69d --- /dev/null +++ b/migrations/003_ingredient_workspace.sql @@ -0,0 +1,48 @@ +ALTER TABLE ingredients ADD COLUMN source_json TEXT NOT NULL DEFAULT '{}'; + +CREATE TABLE ingredient_prep_actions ( + ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE, + action_id TEXT NOT NULL REFERENCES prep_actions(id), + yield_factor REAL NOT NULL CHECK(yield_factor > 0 AND yield_factor <= 1), + notes TEXT, + PRIMARY KEY (ingredient_id, action_id) +); + +CREATE TABLE ingredient_measure_conversions ( + ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE, + id TEXT NOT NULL, + from_quantity REAL NOT NULL, + from_unit_id TEXT NOT NULL REFERENCES units(id), + to_quantity REAL NOT NULL, + to_unit_id TEXT NOT NULL REFERENCES units(id), + state TEXT, + source_json TEXT NOT NULL, + PRIMARY KEY (ingredient_id, id) +); + +CREATE TABLE ingredient_density_measurements ( + ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE, + id TEXT NOT NULL, + mass_quantity REAL NOT NULL, + mass_unit_id TEXT NOT NULL REFERENCES units(id), + volume_quantity REAL NOT NULL, + volume_unit_id TEXT NOT NULL REFERENCES units(id), + temperature_c REAL, + state TEXT, + source_json TEXT NOT NULL, + PRIMARY KEY (ingredient_id, id) +); + +CREATE TABLE collections ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + description TEXT, + source_json TEXT NOT NULL +); + +CREATE TABLE collection_recipes ( + collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE, + recipe_id TEXT NOT NULL REFERENCES recipes(id), + position INTEGER NOT NULL, + PRIMARY KEY (collection_id, recipe_id) +); diff --git a/migrations/004_recipe_measure_conversions.sql b/migrations/004_recipe_measure_conversions.sql new file mode 100644 index 0000000..9d6274e --- /dev/null +++ b/migrations/004_recipe_measure_conversions.sql @@ -0,0 +1,11 @@ +CREATE TABLE recipe_measure_conversions ( + recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, + id TEXT NOT NULL, + from_quantity REAL NOT NULL CHECK (from_quantity > 0), + from_unit_id TEXT NOT NULL REFERENCES units(id), + to_quantity REAL NOT NULL CHECK (to_quantity > 0), + to_unit_id TEXT NOT NULL REFERENCES units(id), + notes TEXT, + source_json TEXT NOT NULL DEFAULT '{}', + PRIMARY KEY (recipe_id, id) +); diff --git a/migrations/005_culinary_workflows.sql b/migrations/005_culinary_workflows.sql new file mode 100644 index 0000000..d681b5a --- /dev/null +++ b/migrations/005_culinary_workflows.sql @@ -0,0 +1,21 @@ +ALTER TABLE recipe_items ADD COLUMN nutrition_retention_factor REAL NOT NULL DEFAULT 1 CHECK(nutrition_retention_factor >= 0 AND nutrition_retention_factor <= 1); +ALTER TABLE recipes ADD COLUMN auto_yield INTEGER NOT NULL DEFAULT 0; +ALTER TABLE recipes ADD COLUMN station TEXT; +ALTER TABLE recipes ADD COLUMN deleted_at TEXT; +ALTER TABLE recipes ADD COLUMN cover_media_url TEXT; +ALTER TABLE ingredients ADD COLUMN deleted_at TEXT; +ALTER TABLE collections ADD COLUMN deleted_at TEXT; + +CREATE TABLE recipe_media ( + recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, + id TEXT NOT NULL, + step_id TEXT, + media_type TEXT NOT NULL CHECK(media_type IN ('image','video')), + url TEXT NOT NULL, + caption TEXT, + position INTEGER NOT NULL, + PRIMARY KEY (recipe_id,id), + FOREIGN KEY (recipe_id,step_id) REFERENCES recipe_steps(recipe_id,id) ON DELETE CASCADE +); + +CREATE INDEX recipe_media_recipe_idx ON recipe_media(recipe_id,position); diff --git a/migrations/006_allow_prep_yield_gain.sql b/migrations/006_allow_prep_yield_gain.sql new file mode 100644 index 0000000..095a8ed --- /dev/null +++ b/migrations/006_allow_prep_yield_gain.sql @@ -0,0 +1,14 @@ +CREATE TABLE ingredient_prep_actions_new ( + ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE, + action_id TEXT NOT NULL REFERENCES prep_actions(id), + yield_factor REAL NOT NULL CHECK(yield_factor > 0), + notes TEXT, + PRIMARY KEY (ingredient_id, action_id) +); + +INSERT INTO ingredient_prep_actions_new (ingredient_id, action_id, yield_factor, notes) +SELECT ingredient_id, action_id, yield_factor, notes +FROM ingredient_prep_actions; + +DROP TABLE ingredient_prep_actions; +ALTER TABLE ingredient_prep_actions_new RENAME TO ingredient_prep_actions; diff --git a/migrations/007_ingredient_editor_fields.sql b/migrations/007_ingredient_editor_fields.sql new file mode 100644 index 0000000..527d6e8 --- /dev/null +++ b/migrations/007_ingredient_editor_fields.sql @@ -0,0 +1,10 @@ +ALTER TABLE ingredients ADD COLUMN description TEXT; +ALTER TABLE ingredients ADD COLUMN tags_json TEXT NOT NULL DEFAULT '[]'; + +UPDATE ingredients +SET tags_json = categories_json; + +UPDATE ingredients +SET description = json_extract(source_json, '$.description') +WHERE json_valid(source_json) + AND json_type(source_json, '$.description') = 'text'; diff --git a/migrations/008_separate_ingredient_tags.sql b/migrations/008_separate_ingredient_tags.sql new file mode 100644 index 0000000..0497ad1 --- /dev/null +++ b/migrations/008_separate_ingredient_tags.sql @@ -0,0 +1,3 @@ +UPDATE ingredients +SET tags_json = '[]' +WHERE tags_json = categories_json; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..89bcc2f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6472 @@ +{ + "name": "recipe-book", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "recipe-book", + "dependencies": { + "@astrojs/node": "^11.1.1", + "@astrojs/preact": "6.0.2", + "astro": "7.2.1", + "preact": "10.29.8", + "yaml": "2.9.0" + }, + "devDependencies": { + "@astrojs/check": "0.9.4", + "@types/node": "^22.10.0", + "typescript": "5.9.2", + "vitest": "4.1.10" + }, + "engines": { + "node": ">=22.12.0", + "npm": ">=9.6.5" + } + }, + "node_modules/@astrojs/check": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.4.tgz", + "integrity": "sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==", + "dev": true, + "dependencies": { + "@astrojs/language-server": "^2.15.0", + "chokidar": "^4.0.1", + "kleur": "^4.1.5", + "yargs": "^17.7.2" + }, + "bin": { + "astro-check": "dist/bin.js" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } + }, + "node_modules/@astrojs/compiler": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz", + "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==", + "dev": true + }, + "node_modules/@astrojs/compiler-binding": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.3.2.tgz", + "integrity": "sha512-8w/9CWmYrAJJ8N0SY3O43ws2BgxoW6u3QsD8u2mE140lMYAlwh+tlNoUeSBq22wVheFuiBbR212l6ixZ2IIgCQ==", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@astrojs/compiler-binding-darwin-arm64": "0.3.2", + "@astrojs/compiler-binding-darwin-x64": "0.3.2", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.2", + "@astrojs/compiler-binding-linux-arm64-musl": "0.3.2", + "@astrojs/compiler-binding-linux-x64-gnu": "0.3.2", + "@astrojs/compiler-binding-linux-x64-musl": "0.3.2", + "@astrojs/compiler-binding-wasm32-wasi": "0.3.2", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.2", + "@astrojs/compiler-binding-win32-x64-msvc": "0.3.2" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-arm64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.3.2.tgz", + "integrity": "sha512-MM8tn8CSimcfytaOla4b6acN8mKWiL/rlAA1fpT3/Wl7dNGSE4y8FjTN/zJVNnb63CsLWG5zZwCt01TXtDKh9g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-x64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.3.2.tgz", + "integrity": "sha512-2lXOlzf8xb7jLomRsf/aswh61/NnGusynB2OwFkK6k4pmOtpfXMYnG0PLfXrEvxXYj69NdCnmUYXtHDd+JOOag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.3.2.tgz", + "integrity": "sha512-BmU3kWj7qnLrd4vzm49zFEPJ5oFnn1tCT4Vt9hZbqdU5Cmb8GZl7fn6VFsnNfe7B18a2gIFtVzbLINtYl5kBjQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.3.2.tgz", + "integrity": "sha512-f0heT9ZZEseSu5bHCeb80eL2DH07ArE6U9xi1WT/PEusNjzPmEr3GJsjG1tRLo5VYUUYX7h3ScaqGmGrMOVGmw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.3.2.tgz", + "integrity": "sha512-M8fOUt0itRpqiGyoEA/ij184s8O+hqbCz3+YozRusOOM3osgGljpDThhbKAJjqh82wOo6FioQ4w8PBvU1XMD5Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.3.2.tgz", + "integrity": "sha512-/Kebk8sO6HnLeSd691JkaAPfN7CqR9/KEXmWvyNPkaKNGmj8rTZ/lf2uXtnPu92Lan84UrKdIKVPy1fSo2encQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-wasm32-wasi": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.3.2.tgz", + "integrity": "sha512-pUA6xbcOSB7DhfzIArB8BCAkFfAIqriiR7zl5zOStd6oU2G0kIKj+GUdGnyXyhfiv881Hffyk5tC0mR18sDjDw==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.3.2.tgz", + "integrity": "sha512-ESruf+6Qkl1trHUFxI6GSf6t52j8yN2kCNSzMWdzt7V/T09tFHrYzrVaJQohb2C9bJUH76pNvX6Zb51+xCQc9Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-x64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.3.2.tgz", + "integrity": "sha512-wzzVrEbOwbsLWOdEbocskjMRx2aZPxJ7ZbmL+jnpBamFwmigm+2M/wzuM6JWncocgYwLic1csSpalBh96kQKXA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-rs": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.3.2.tgz", + "integrity": "sha512-xlx/T7JovIKduu4ucbTQUxQ5+Q8wxkHxhLjnZk3VlJbhbQ9RLvvuDk1p2YYFYFQ5y14dVm3FGGO4isQXa4F+Tg==", + "dependencies": { + "@astrojs/compiler-binding": "0.3.2" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.2.tgz", + "integrity": "sha512-yt7fMgPYqSM4Tmr+taTW6Per+hjJ8Pk6lA1PAcDyqzOt8HzJ6Kje5WzCxA2Sd+9wsUW7uhkLeoTMK0cXPwH9rQ==", + "dependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.3.0", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" + } + }, + "node_modules/@astrojs/language-server": { + "version": "2.16.14", + "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.14.tgz", + "integrity": "sha512-YPXkBu6N4d1sT09pvBmIDGZay+1MemV551FSgdEM3aZRDzbkxd2H7Cvf8MsVJLVB1mIEyTf1XbMN/30gp7s46w==", + "dev": true, + "dependencies": { + "@astrojs/compiler": "^2.13.1", + "@astrojs/yaml2ts": "^0.2.4", + "@jridgewell/sourcemap-codec": "^1.5.5", + "@volar/kit": "~2.4.28", + "@volar/language-core": "~2.4.28", + "@volar/language-server": "~2.4.28", + "@volar/language-service": "~2.4.28", + "muggle-string": "^0.4.1", + "tinyglobby": "^0.2.16", + "volar-service-css": "0.0.71", + "volar-service-emmet": "0.0.71", + "volar-service-html": "0.0.71", + "volar-service-prettier": "0.0.71", + "volar-service-typescript": "0.0.71", + "volar-service-typescript-twoslash-queries": "0.0.71", + "volar-service-yaml": "0.0.71", + "vscode-html-languageservice": "^5.6.2", + "vscode-uri": "^3.1.0" + }, + "bin": { + "astro-ls": "bin/nodeServer.js" + }, + "peerDependencies": { + "prettier": "^3.0.0", + "prettier-plugin-astro": ">=0.11.0" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + } + } + }, + "node_modules/@astrojs/markdown-satteri": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.5.tgz", + "integrity": "sha512-CvWVEFAbay7YO+i9SaqDJubipA5ckiVB89QWoMJ5XC0m5CtFg8JwZ7Kau6X9sYY7FZURH0w2l03ISH2jOS/RDQ==", + "dependencies": { + "@astrojs/internal-helpers": "0.10.2", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "satteri": "^0.9.1" + } + }, + "node_modules/@astrojs/node": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-11.1.1.tgz", + "integrity": "sha512-zST8STilReHpbyafO16s8HB5vw9eJcIT/Vpjhz6Q/gv5LcuX7pk4Quz85NQpHl4liXZuR41IPN1hZbeZ7cSjCg==", + "dependencies": { + "@astrojs/internal-helpers": "0.10.2", + "send": "^1.2.1", + "server-destroy": "^1.0.1" + }, + "peerDependencies": { + "astro": "^7.0.0" + } + }, + "node_modules/@astrojs/preact": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@astrojs/preact/-/preact-6.0.2.tgz", + "integrity": "sha512-OoV/1KeGpRU8f9a+jBk2q2GK05jqjnRg7H+ZN8i48FBKrLJQj+4nU/Vg+JSsvhZ9PZtku0kS2vyFBJ8SGXoTiQ==", + "dependencies": { + "@astrojs/internal-helpers": "0.10.2", + "@preact/preset-vite": "^2.10.5", + "@preact/signals": "^2.8.2", + "devalue": "^5.8.1", + "preact-render-to-string": "^6.6.6", + "vite": "^8.0.13" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "preact": "^10.6.5" + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", + "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", + "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "dependencies": { + "ci-info": "^4.4.0", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "package-manager-detector": "^1.6.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@astrojs/yaml2ts": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.4.tgz", + "integrity": "sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A==", + "dev": true, + "dependencies": { + "yaml": "^2.8.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bruits/satteri-darwin-arm64": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.9.5.tgz", + "integrity": "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-darwin-x64": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.9.5.tgz", + "integrity": "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-gnu": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.9.5.tgz", + "integrity": "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-musl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.9.5.tgz", + "integrity": "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-gnu": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.9.5.tgz", + "integrity": "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-musl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.9.5.tgz", + "integrity": "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-wasm32-wasi": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.9.5.tgz", + "integrity": "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-win32-arm64-msvc": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.9.5.tgz", + "integrity": "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@bruits/satteri-win32-x64-msvc": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.9.5.tgz", + "integrity": "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz", + "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==", + "dependencies": { + "fontkitten": "^1.0.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@clack/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", + "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", + "dependencies": { + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@clack/prompts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", + "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", + "dependencies": { + "@clack/core": "1.4.3", + "fast-string-width": "^3.0.2", + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@emmetio/abbreviation": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", + "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==", + "dev": true, + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/css-abbreviation": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz", + "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==", + "dev": true, + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/css-parser": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@emmetio/css-parser/-/css-parser-0.4.1.tgz", + "integrity": "sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==", + "dev": true, + "dependencies": { + "@emmetio/stream-reader": "^2.2.0", + "@emmetio/stream-reader-utils": "^0.1.0" + } + }, + "node_modules/@emmetio/html-matcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emmetio/html-matcher/-/html-matcher-1.3.0.tgz", + "integrity": "sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==", + "dev": true, + "dependencies": { + "@emmetio/scanner": "^1.0.0" + } + }, + "node_modules/@emmetio/scanner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz", + "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==", + "dev": true + }, + "node_modules/@emmetio/stream-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz", + "integrity": "sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==", + "dev": true + }, + "node_modules/@emmetio/stream-reader-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@emmetio/stream-reader-utils/-/stream-reader-utils-0.1.0.tgz", + "integrity": "sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==", + "dev": true + }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", + "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==" + }, + "node_modules/@oxc-project/types": { + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@preact/preset-vite": { + "version": "2.10.6", + "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.10.6.tgz", + "integrity": "sha512-ZZ5RIT2ZVXg8UxRA8VZpoT8CdpDG7RFIqOT4bELqNBp85+HKvQBbgmh3gsoW1UOQXx26TLe+ZRNKI7q281Kckw==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@prefresh/vite": "^2.4.11", + "@rollup/pluginutils": "^5.0.0", + "babel-plugin-transform-hook-names": "^1.0.2", + "debug": "^4.4.3", + "magic-string": "^0.30.21", + "picocolors": "^1.1.1", + "vite-prerender-plugin": "^0.5.8", + "zimmerframe": "^1.1.4" + }, + "peerDependencies": { + "@babel/core": "7.x", + "vite": "2.x || 3.x || 4.x || 5.x || 6.x || 7.x || 8.x" + } + }, + "node_modules/@preact/signals": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-2.11.0.tgz", + "integrity": "sha512-mmrZ8I/Wef+tmSsQSjZySLRlnvuYAVfSZEy1+HrFvSwBtQf8/zSM+bV7odllUXIhKzUkBjsNk+TLZ20nt7p6Gg==", + "dependencies": { + "@preact/signals-core": "^1.14.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": ">= 10.25.0 || >=11.0.0-0" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.4.tgz", + "integrity": "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/@prefresh/babel-plugin": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@prefresh/babel-plugin/-/babel-plugin-0.5.3.tgz", + "integrity": "sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ==" + }, + "node_modules/@prefresh/core": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/@prefresh/core/-/core-1.5.10.tgz", + "integrity": "sha512-7yPTFbG56sutaFu8krp3B4a200KOFUvrtlllKWRuLjsYXo9UUucHOZRcer+gtgMkFTpv6ob8TGcTwA32bSwa1w==", + "peerDependencies": { + "preact": "^10.0.0 || ^11.0.0-0" + } + }, + "node_modules/@prefresh/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@prefresh/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" + }, + "node_modules/@prefresh/vite": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/@prefresh/vite/-/vite-2.4.12.tgz", + "integrity": "sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA==", + "dependencies": { + "@babel/core": "^7.22.1", + "@prefresh/babel-plugin": "^0.5.2", + "@prefresh/core": "^1.5.0", + "@prefresh/utils": "^1.2.0", + "@rollup/pluginutils": "^4.2.1" + }, + "peerDependencies": { + "preact": "^10.4.0 || ^11.0.0-0", + "vite": ">=2.0.0" + } + }, + "node_modules/@prefresh/vite/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@prefresh/vite/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@shikijs/core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "dependencies": { + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "devOptional": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==" + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/kit": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.28.tgz", + "integrity": "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==", + "dev": true, + "dependencies": { + "@volar/language-service": "2.4.28", + "@volar/typescript": "2.4.28", + "typesafe-path": "^0.2.2", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/language-server": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.28.tgz", + "integrity": "sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.28", + "@volar/language-service": "2.4.28", + "@volar/typescript": "2.4.28", + "path-browserify": "^1.0.1", + "request-light": "^0.7.0", + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-protocol": "^3.17.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@volar/language-service": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.28.tgz", + "integrity": "sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.28", + "vscode-languageserver-protocol": "^3.17.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vscode/emmet-helper": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@vscode/emmet-helper/-/emmet-helper-2.11.0.tgz", + "integrity": "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==", + "dev": true, + "dependencies": { + "emmet": "^2.4.3", + "jsonc-parser": "^2.3.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.15.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vscode/l10n": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz", + "integrity": "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==", + "dev": true + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-i18n": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ajv-i18n/-/ajv-i18n-4.2.0.tgz", + "integrity": "sha512-v/ei2UkCEeuKNXh8RToiFsUclmU+G57LO1Oo22OagNMENIw+Yb8eMwvHu7Vn9fmkjJyv6XclhJ8TbuigSglPkg==", + "dev": true, + "peerDependencies": { + "ajv": "^8.0.0-beta.0" + } + }, + "node_modules/am-i-vibing": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.4.0.tgz", + "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "dependencies": { + "process-ancestry": "^0.1.0" + }, + "bin": { + "am-i-vibing": "dist/cli.mjs" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/astro": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.2.1.tgz", + "integrity": "sha512-ynyMTiyF//GLcd8+gRNbvcKgS1ht+qTgp/fkkHIpGYNILLseQqQRuPZ9PqXYKfsact4J1emZaXRDpg2bl35Pag==", + "dependencies": { + "@astrojs/compiler-rs": "^0.3.2", + "@astrojs/internal-helpers": "0.10.2", + "@astrojs/markdown-satteri": "0.3.5", + "@astrojs/telemetry": "3.3.3", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "am-i-vibing": "^0.4.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "ci-info": "^4.4.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^2.0.0", + "cookie": "^2.0.1", + "devalue": "^5.8.1", + "diff": "^8.0.3", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.28.0", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "get-tsconfig": "5.0.0-beta.4", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.3.0", + "jsonc-parser": "^3.3.1", + "magic-string": "^1.0.0", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^1.0.1", + "obug": "^2.1.1", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.4", + "semver": "^7.7.4", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "svgo": "^4.0.1", + "tinyclip": "^0.1.12", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.4", + "unstorage": "^1.17.5", + "vite": "^8.0.13", + "vitefu": "^1.1.2", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^22.0.0", + "zod": "^4.3.6" + }, + "bin": { + "astro": "bin/astro.mjs" + }, + "engines": { + "node": ">=22.12.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.34.0 || ^0.35.0" + }, + "peerDependencies": { + "@astrojs/markdown-remark": "7.2.2" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-remark": { + "optional": true + } + } + }, + "node_modules/astro/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + "node_modules/astro/node_modules/magic-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.1.0.tgz", + "integrity": "sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/astro/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/astro/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-plugin-transform-hook-names": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-hook-names/-/babel-plugin-transform-hook-names-1.0.2.tgz", + "integrity": "sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==", + "peerDependencies": { + "@babel/core": "^7.12.10" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", + "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "engines": { + "node": ">= 18" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==", + "engines": { + "node": ">=22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==" + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.0.tgz", + "integrity": "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A==" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.405", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.405.tgz", + "integrity": "sha512-bNglH7lPH5l+yHOes7Zr4VqxhOy4BQ9ZBUX4VdoFgxMpzJk7W1ZoO3Vgd9Pxa9PyjQ76sfm2aKH/nzEcCNRlew==" + }, + "node_modules/emmet": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.11.tgz", + "integrity": "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==", + "dev": true, + "dependencies": { + "@emmetio/abbreviation": "^2.3.3", + "@emmetio/css-abbreviation": "^2.1.8" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==" + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==" + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", + "dependencies": { + "fontkitten": "^1.0.2" + } + }, + "node_modules/fontkitten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", + "dependencies": { + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-tsconfig": { + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", + "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "engines": { + "node": ">=20.20.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-docker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz", + "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", + "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==" + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-1.0.1.tgz", + "integrity": "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==" + }, + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, + "node_modules/node-mock-http": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.5.tgz", + "integrity": "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==" + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/p-limit": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz", + "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==", + "dependencies": { + "yocto-queue": "^1.2.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", + "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "dependencies": { + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.29.8", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.8.tgz", + "integrity": "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, + "node_modules/preact-render-to-string": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.7.0.tgz", + "integrity": "sha512-Z4WR8fmLMRpdYqJ9i7vrlXSsSrxVJydwrkEXHapexfARbWfGb7vGcnvNQnIzN0cXciMVOlz/XLoiMCi9gUsy9Q==", + "peerDependencies": { + "preact": ">=10 || >= 11.0.0-0" + } + }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-ancestry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/process-ancestry/-/process-ancestry-0.1.0.tgz", + "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==" + }, + "node_modules/range-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", + "engines": { + "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==" + }, + "node_modules/request-light": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.7.0.tgz", + "integrity": "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rolldown": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "dependencies": { + "@oxc-project/types": "=0.143.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" + } + }, + "node_modules/rollup": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", + "optional": true, + "peer": true, + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/satteri": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.9.5.tgz", + "integrity": "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==", + "dependencies": { + "@types/estree-jsx": "^1.0.5", + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "@types/unist": "^3.0.3" + }, + "optionalDependencies": { + "@bruits/satteri-darwin-arm64": "0.9.5", + "@bruits/satteri-darwin-x64": "0.9.5", + "@bruits/satteri-linux-arm64-gnu": "0.9.5", + "@bruits/satteri-linux-arm64-musl": "0.9.5", + "@bruits/satteri-linux-x64-gnu": "0.9.5", + "@bruits/satteri-linux-x64-musl": "0.9.5", + "@bruits/satteri-wasm32-wasi": "0.9.5", + "@bruits/satteri-win32-arm64-msvc": "0.9.5", + "@bruits/satteri-win32-x64-msvc": "0.9.5" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shiki": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "dependencies": { + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/simple-code-frame": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/simple-code-frame/-/simple-code-frame-1.3.0.tgz", + "integrity": "sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==", + "dependencies": { + "kolorist": "^1.6.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/smol-toml": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", + "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-1.0.0.tgz", + "integrity": "sha512-H6D7134xi6qONvh7ZHKgviXf+rd3vhGBSvebPZCaUkd8zvQ+7PtDw6CljPTe4cXWNf2IKZGNqw6VJXSb9IgBpA==", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz", + "integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinyclip": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", + "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "optional": true + }, + "node_modules/typesafe-path": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz", + "integrity": "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-auto-import-cache": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.6.tgz", + "integrity": "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==", + "dev": true, + "dependencies": { + "semver": "^7.3.8" + } + }, + "node_modules/typescript-auto-import-cache/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==" + }, + "node_modules/ultrahtml": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz", + "integrity": "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", + "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", + "dependencies": { + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/unstorage/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/unstorage/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/unstorage/node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-prerender-plugin": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/vite-prerender-plugin/-/vite-prerender-plugin-0.5.13.tgz", + "integrity": "sha512-IKSpYkzDBsKAxa05naRbj7GvNVMSdww/Z/E89oO3xndz+gWnOBOKOAbEXv7qDhktY/j3vHgJmoV1pPzqU2tx9g==", + "dependencies": { + "kolorist": "^1.8.0", + "magic-string": "0.x >= 0.26.0", + "node-html-parser": "^6.1.12", + "simple-code-frame": "^1.3.0", + "source-map": "^0.7.4", + "stack-trace": "^1.0.0-pre2" + }, + "peerDependencies": { + "vite": "5.x || 6.x || 7.x || 8.x" + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/volar-service-css": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.71.tgz", + "integrity": "sha512-wRRFt9BpjMKCazcgOh67MSjUjiWUCAh99DyYSDIOTuxaRjEtDC7PpB0k1Y1wbJIW/pVtMUSVbpPo3UGSm0Byxw==", + "dev": true, + "dependencies": { + "vscode-css-languageservice": "^6.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-emmet": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.71.tgz", + "integrity": "sha512-zqjzt6bN95e3CUstBm0PBFAJnrfz0ZAARka87fart46/gNCLLuP3Vujy8V/J8HEziTFLnfkgIASLFYPUhonJcA==", + "dev": true, + "dependencies": { + "@emmetio/css-parser": "^0.4.1", + "@emmetio/html-matcher": "^1.3.0", + "@vscode/emmet-helper": "^2.9.3", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-html": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.71.tgz", + "integrity": "sha512-e8tHPhgQ7ooLfudAEIku+kgd9pWkq3SSz8RbnQDI1+Eb8wbenkLGHqoirLqz5ORLV6wIMr2Iv08RWBG5eOcgpw==", + "dev": true, + "dependencies": { + "vscode-html-languageservice": "^5.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-prettier": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.71.tgz", + "integrity": "sha512-Rz7JVH3qD108UCdmIEiZvOBNljMt2nLFdbN8AXcDfn7xD9F5I2aCIsDVqBbXw21PsnxG0b7MfwtNF+zPS/NKUg==", + "dev": true, + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0", + "prettier": "^2.2 || ^3.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + }, + "prettier": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.71.tgz", + "integrity": "sha512-yTtM/BVT6hoyEYnDtaCyAtNhdNeS/mhTTABlBOdw3NNiRBUin3IznFJpgfjer4c6RYopiPjjQjc9VFhxVl1mLw==", + "dev": true, + "dependencies": { + "path-browserify": "^1.0.1", + "semver": "^7.6.2", + "typescript-auto-import-cache": "^0.3.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-nls": "^5.2.0", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript-twoslash-queries": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.71.tgz", + "integrity": "sha512-9K2k72s4n7rV9s4bX0MyjbX9iBribvKZbBJKuEmTCZfeWJXs6Yh7bGpY4eoc7UufAjvpheBqwyZCOIPBvxCv0A==", + "dev": true, + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/volar-service-yaml": { + "version": "0.0.71", + "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.71.tgz", + "integrity": "sha512-qYGWGuVpUTnZGu5P/CR4KLK4aIR8RrcVnmfZ2eRcj9q/I8VZCoC5yy9FtEvfNvnDp4MU17yhdJcvpQPIqhJS2Q==", + "dev": true, + "dependencies": { + "vscode-uri": "^3.0.8", + "yaml-language-server": "~1.23.0" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/vscode-css-languageservice": { + "version": "6.3.10", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.10.tgz", + "integrity": "sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==", + "dev": true, + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "3.17.5", + "vscode-uri": "^3.1.0" + } + }, + "node_modules/vscode-css-languageservice/node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "node_modules/vscode-html-languageservice": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.6.2.tgz", + "integrity": "sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==", + "dev": true, + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.1.0" + } + }, + "node_modules/vscode-json-languageservice": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz", + "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + }, + "engines": { + "npm": ">=7.0.0" + } + }, + "node_modules/vscode-json-languageservice/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true + }, + "node_modules/vscode-jsonrpc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.1.tgz", + "integrity": "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.18.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.2.tgz", + "integrity": "sha512-XRyDbT0Pp3sSNti3JmxVEUMySWCSi1hhM+/KUlCy1hV1zmrqpM1OwO12EAki8blhmLuIMpaJrYbo0OzGVfK2Qg==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "9.0.1", + "vscode-languageserver-types": "3.18.0" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", + "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", + "dev": true + }, + "node_modules/vscode-languageserver/node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver/node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver/node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "node_modules/vscode-nls": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yaml-language-server": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.23.0.tgz", + "integrity": "sha512-3qVyCOexLCWw06PQa5kRPwvMWMZ/eZeCRWUvgD6a0OkqL/4iCnxy2WumbWifa937Uo5xhyWJ0uxlU39ljhNh7A==", + "dev": true, + "dependencies": { + "@vscode/l10n": "^0.0.18", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "ajv-i18n": "^4.2.0", + "prettier": "^3.8.1", + "request-light": "^0.5.7", + "vscode-json-languageservice": "4.1.8", + "vscode-languageserver": "^9.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-uri": "^3.0.2", + "yaml": "2.8.3" + }, + "bin": { + "yaml-language-server": "bin/yaml-language-server" + } + }, + "node_modules/yaml-language-server/node_modules/request-light": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz", + "integrity": "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==", + "dev": true + }, + "node_modules/yaml-language-server/node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==" + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2cec7b0 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "recipe-book", + "private": true, + "type": "module", + "engines": { + "node": ">=22.12.0", + "npm": ">=9.6.5" + }, + "scripts": { + "dev": "npm run dev:site", + "dev:site": "npm run site:project && astro dev --config astro.config.mjs --port 4321", + "dev:app": "astro dev --config astro.app.config.mjs --port 4322", + "restart:app": "node scripts/restart-app.mjs", + "check": "npm run check:site && npm run check:app", + "check:site": "npm run site:project && astro check --config astro.config.mjs", + "check:app": "astro check --config astro.app.config.mjs", + "build": "npm run build:site && npm run build:app", + "build:site": "npm run site:project && astro check --config astro.config.mjs && astro build --config astro.config.mjs", + "build:app": "astro check --config astro.app.config.mjs && astro build --config astro.app.config.mjs", + "preview": "npm run preview:site", + "preview:site": "astro preview --config astro.config.mjs --port 4321", + "preview:app": "astro preview --config astro.app.config.mjs --port 4322", + "test": "vitest run", + "site:project": "node scripts/site-project.mjs", + "db:sync": "npm run db:migrate", + "db:migrate": "node scripts/db-migrate.mjs", + "db:reset": "node scripts/db-sync.mjs --reset", + "db:import:yaml": "node scripts/db-sync.mjs --reset" + }, + "dependencies": { + "@astrojs/node": "^11.1.1", + "@astrojs/preact": "6.0.2", + "astro": "7.2.1", + "preact": "10.29.8", + "yaml": "2.9.0" + }, + "devDependencies": { + "@astrojs/check": "0.9.4", + "@types/node": "^22.10.0", + "typescript": "5.9.2", + "vitest": "4.1.10" + } +} diff --git a/public/W.svg b/public/W.svg new file mode 100644 index 0000000..22c2523 --- /dev/null +++ b/public/W.svg @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..a72cd2f Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png new file mode 100644 index 0000000..949b7dd Binary files /dev/null and b/public/favicon-96x96.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..13b2e5b Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..45e4d4d --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..c4453c1 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "Recipe Book - Nicholas Ward", + "short_name": "recipes", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/public/web-app-manifest-192x192.png b/public/web-app-manifest-192x192.png new file mode 100644 index 0000000..fa609cf Binary files /dev/null and b/public/web-app-manifest-192x192.png differ diff --git a/public/web-app-manifest-512x512.png b/public/web-app-manifest-512x512.png new file mode 100644 index 0000000..bc1ad5e Binary files /dev/null and b/public/web-app-manifest-512x512.png differ diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..dc045ca --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +jsonschema>=4.18,<5 +PyYAML>=6,<7 diff --git a/scripts/corpus-export b/scripts/corpus-export new file mode 100755 index 0000000..a6ef06f --- /dev/null +++ b/scripts/corpus-export @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +"""Export canonical culinary recipes as clean Markdown knowledge documents.""" + +from __future__ import annotations + +import argparse +import shutil +import tempfile +from pathlib import Path + +import yaml + + +ROOT = Path(__file__).resolve().parent.parent +CULINARY_DIR = ROOT / "culinary" +DEFAULT_OUTPUT = ROOT / "generated/open-webui/recipes" + + +def load_entities(directory: Path) -> dict[str, dict]: + entities = {} + for path in sorted(directory.glob("*.yaml")): + data = yaml.safe_load(path.read_text(encoding="utf-8")) + entity_id = data["id"] + if entity_id in entities: + raise ValueError(f"duplicate ID {entity_id!r} in {directory}") + entities[entity_id] = data + return entities + + +def amount_text(amount: dict | None) -> str: + if not amount: + return "—" + display = amount.get("display") + if display: + return display + quantity = amount["quantity"] + maximum = amount.get("quantity_max") + value = f"{quantity:g}" if isinstance(quantity, float) else str(quantity) + if maximum is not None: + upper = f"{maximum:g}" if isinstance(maximum, float) else str(maximum) + value = f"{value}–{upper}" + return f"{value} {amount['unit_id'].replace('_', ' ')}" + + +def render_recipe(recipe: dict, ingredients: dict[str, dict], recipes: dict[str, dict]) -> str: + lines = [f"# {recipe['title']}", ""] + lines.extend( + [ + f"Recipe ID: `{recipe['id']}`", + f"Revision: {recipe['revision']}", + f"Status: {recipe['status']}", + f"Categories: {', '.join(recipe['categories']) or 'None'}", + f"Tags: {', '.join(recipe['tags']) or 'None'}", + f"Yield: {amount_text(recipe['yield']['amount'])}", + ] + ) + if recipe["yield"].get("servings") is not None: + lines.append(f"Servings: {recipe['yield']['servings']:g}") + if recipe["yield"].get("description"): + lines.append(f"Yield description: {recipe['yield']['description']}") + lines.append("") + + for component in recipe["components"]: + lines.extend([f"## {component['name']}", "", "| Item | Amount | Formula percentage |", "| --- | ---: | ---: |"]) + for item in component["items"]: + reference = item["reference"] + if "ingredient_id" in reference: + item_id = reference["ingredient_id"] + label = ingredients[item_id]["name"] + else: + item_id = reference["recipe_id"] + label = f"{recipes[item_id]['title']} (sub-recipe)" + percentage = f"{item['percentage']:g}%" if "percentage" in item else "—" + lines.append(f"| {label} | {amount_text(item['amount'])} | {percentage} |") + if component.get("notes"): + lines.extend(["", *[f"- {note}" for note in component["notes"]]]) + lines.append("") + + lines.extend(["## Preparation", ""]) + for step in sorted(recipe["steps"], key=lambda value: value["order"]): + lines.append(f"{step['order']}. {step['instruction']}") + if recipe.get("notes"): + lines.extend(["", "## Notes", "", *[f"- {note}" for note in recipe["notes"]]]) + return "\n".join(lines).rstrip() + "\n" + + +def parse_args(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("output", nargs="?", type=Path, default=DEFAULT_OUTPUT) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + output = args.output.resolve() + if output in {Path("/"), ROOT}: + raise ValueError(f"refusing unsafe output directory: {output}") + ingredients = load_entities(CULINARY_DIR / "ingredients") + recipes = load_entities(CULINARY_DIR / "recipes") + output.parent.mkdir(parents=True, exist_ok=True) + staging = Path(tempfile.mkdtemp(prefix="recipe-corpus-", dir=output.parent)) + try: + for recipe_id, recipe in recipes.items(): + (staging / f"{recipe_id}.md").write_text( + render_recipe(recipe, ingredients, recipes), encoding="utf-8" + ) + if output.exists(): + shutil.rmtree(output) + staging.replace(output) + except Exception: + shutil.rmtree(staging, ignore_errors=True) + raise + print(f"Exported {len(recipes)} canonical recipes to {output}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/db-migrate.mjs b/scripts/db-migrate.mjs new file mode 100644 index 0000000..43a4df8 --- /dev/null +++ b/scripts/db-migrate.mjs @@ -0,0 +1,16 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import path from "node:path"; +import { DatabaseSync } from "node:sqlite"; +import { applyMigrations } from "./lib/migrations.mjs"; + +const databasePath = path.resolve(process.cwd(), "var", "recipe-book.sqlite"); +if (!fs.existsSync(databasePath)) throw new Error(`Database does not exist: ${databasePath}. Run npm run db:sync once to import the initial data.`); +const database = new DatabaseSync(databasePath); +database.exec("PRAGMA foreign_keys = ON; PRAGMA journal_mode = WAL;"); +try { + const applied = applyMigrations(database); + console.log(applied.length ? `Applied ${applied.join(", ")}` : "Database schema is current."); +} finally { + database.close(); +} diff --git a/scripts/db-sync.mjs b/scripts/db-sync.mjs new file mode 100644 index 0000000..a81d489 --- /dev/null +++ b/scripts/db-sync.mjs @@ -0,0 +1,82 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import path from "node:path"; +import process from "node:process"; +import { DatabaseSync } from "node:sqlite"; +import YAML from "yaml"; +import { applyMigrations } from "./lib/migrations.mjs"; +import { writeSiteProjection } from "./lib/site-projection.mjs"; + +const root = path.resolve(import.meta.dirname, ".."); +const databasePath = path.join(root, "var", "recipe-book.sqlite"); +if (!process.argv.includes("--reset")) throw new Error("YAML import replaces the canonical database. Re-run with --reset, or use npm run db:migrate for a safe schema upgrade."); +if (fs.existsSync(databasePath)) fs.rmSync(databasePath); +fs.mkdirSync(path.dirname(databasePath), { recursive: true }); +const db = new DatabaseSync(databasePath); +db.exec("PRAGMA foreign_keys = ON; PRAGMA journal_mode = WAL;"); + +const records = (directory) => { + const location = path.join(root, "culinary", directory); + if (!fs.existsSync(location)) return []; + return fs.readdirSync(location).filter((name) => name.endsWith(".yaml")).sort().map((name) => YAML.parse(fs.readFileSync(path.join(location, name), "utf8"))); +}; +const run = (sql, values) => db.prepare(sql).run(...values); +const json = (value) => JSON.stringify(value ?? []); + +applyMigrations(db, { migrationsDirectory: path.join(root, "migrations") }); + +db.exec("BEGIN IMMEDIATE"); +try { + db.exec("PRAGMA defer_foreign_keys = ON"); + for (const table of ["collection_recipes", "collections", "recipe_measure_conversions", "ingredient_density_measurements", "ingredient_measure_conversions", "ingredient_prep_actions", "step_equipment", "recipe_equipment", "item_prep_actions", "recipe_steps", "recipe_items", "recipe_components", "price_observations", "purchase_items", "source_mappings", "ingredient_aliases", "recipes", "prep_actions", "equipment", "ingredients", "units"]) db.exec(`DELETE FROM ${table}`); + for (const unit of records("units")) run("INSERT INTO units VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [unit.id, unit.name, unit.symbol, unit.dimension, unit.system, unit.base_conversion?.base_unit_id ?? null, unit.base_conversion?.factor ?? null, unit.base_conversion?.offset ?? null]); + for (const ingredient of records("ingredients")) { + run("INSERT INTO ingredients(id, schema_version, name, status, categories_json, source_json, description, tags_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [ingredient.id, ingredient.schema_version, ingredient.name, ingredient.status, json(ingredient.categories), json(ingredient), ingredient.description ?? null, json(ingredient.tags ?? [])]); + for (const alias of ingredient.aliases ?? []) run("INSERT INTO ingredient_aliases VALUES (?, ?, ?)", [ingredient.id, alias.name, alias.kind ?? null]); + for (const conversion of ingredient.measure_conversions ?? []) run("INSERT INTO ingredient_measure_conversions VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [ingredient.id, conversion.id, conversion.from.quantity, conversion.from.unit_id, conversion.to.quantity, conversion.to.unit_id, conversion.state ?? null, json(conversion.source)]); + for (const density of ingredient.density_measurements ?? []) run("INSERT INTO ingredient_density_measurements VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", [ingredient.id, density.id, density.mass.quantity, density.mass.unit_id, density.volume.quantity, density.volume.unit_id, density.temperature_c ?? null, density.state ?? null, json(density.source)]); + } + for (const item of records("equipment")) run("INSERT INTO equipment VALUES (?, ?, ?, ?)", [item.id, item.name, item.category ?? null, item.notes ?? null]); + for (const action of records("prep_actions")) run("INSERT INTO prep_actions VALUES (?, ?, ?, ?, ?)", [action.id, action.name, action.action_type, action.default_yield_factor ?? null, action.notes ?? null]); + const recipes = records("recipes"); + for (const recipe of recipes) run("INSERT INTO recipes(id, schema_version, revision, status, title, summary, categories_json, tags_json, yield_quantity, yield_unit_id, yield_servings, yield_basis, scaling_mode, scaling_basis_id, scaling_basis_quantity, scaling_basis_unit_id, notes_json, source_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, recipe.schema_version, recipe.revision, recipe.status, recipe.title, recipe.summary ?? null, json(recipe.categories), json(recipe.tags), recipe.yield.amount.quantity, recipe.yield.amount.unit_id, recipe.yield.servings ?? null, recipe.yield.basis ?? null, recipe.scaling?.mode ?? null, recipe.scaling?.basis_id ?? null, recipe.scaling?.basis_amount?.quantity ?? null, recipe.scaling?.basis_amount?.unit_id ?? null, json(recipe.notes), json(recipe)]); + for (const recipe of recipes) { + for (const conversion of recipe.measure_conversions ?? []) run("INSERT INTO recipe_measure_conversions VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, conversion.id, conversion.from.quantity, conversion.from.unit_id, conversion.to.quantity, conversion.to.unit_id, conversion.notes ?? null, json(conversion.source ?? {})]); + for (const [componentPosition, component] of recipe.components.entries()) { + run("INSERT INTO recipe_components VALUES (?, ?, ?, ?, ?)", [recipe.id, component.id, componentPosition + 1, component.name, json(component.notes)]); + for (const [itemPosition, item] of component.items.entries()) { + run("INSERT INTO recipe_items VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, component.id, item.id, itemPosition + 1, item.reference.ingredient_id ?? null, item.reference.recipe_id ?? null, item.reference.revision ?? null, item.amount.quantity, item.amount.unit_id, item.percentage ?? null, item.basis_member ? 1 : 0, item.optional ? 1 : 0, item.notes ?? null]); + for (const [prepPosition, prep] of (item.prep ?? []).entries()) run("INSERT INTO item_prep_actions VALUES (?, ?, ?, ?, ?, ?)", [recipe.id, item.id, prepPosition + 1, prep.action_id, prep.yield_factor ?? null, prep.notes ?? null]); + } + } + for (const step of recipe.steps) { + run("INSERT INTO recipe_steps VALUES (?, ?, ?, ?, ?)", [recipe.id, step.id, step.order, step.instruction, step.critical_control_point ? 1 : 0]); + for (const equipmentId of step.equipment_ids ?? []) run("INSERT INTO step_equipment VALUES (?, ?, ?)", [recipe.id, step.id, equipmentId]); + } + for (const equipmentId of recipe.equipment_ids ?? []) run("INSERT INTO recipe_equipment VALUES (?, ?)", [recipe.id, equipmentId]); + } + for (const ingredient of records("ingredients")) for (const prep of ingredient.prep_actions ?? []) run("INSERT INTO ingredient_prep_actions VALUES (?, ?, ?, ?)", [ingredient.id, prep.action_id, prep.yield_factor, prep.notes ?? null]); + db.exec(`INSERT INTO ingredient_prep_actions(ingredient_id, action_id, yield_factor, notes) + SELECT DISTINCT i.ingredient_id, p.action_id, COALESCE(p.yield_factor, a.default_yield_factor, 1), p.notes + FROM item_prep_actions p JOIN recipe_items i ON i.recipe_id = p.recipe_id AND i.id = p.item_id + JOIN prep_actions a ON a.id = p.action_id WHERE i.ingredient_id IS NOT NULL + ON CONFLICT(ingredient_id, action_id) DO NOTHING`); + for (const item of records("purchase_items")) { + run("INSERT INTO purchase_items VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [item.id, item.ingredient_id, item.name, item.brand ?? null, item.supplier_id ?? null, item.supplier_sku ?? null, item.status, item.package.quantity, item.package.unit_id, item.package.units_per_case ?? 1, item.package.usable_yield_factor ?? 1]); + for (const price of item.prices) run("INSERT INTO price_observations VALUES (?, ?, ?, ?, ?)", [item.id, price.effective_at, price.currency, price.amount, json(price.source)]); + } + for (const mapping of records("source_mappings")) run("INSERT INTO source_mappings VALUES (?, ?, ?, ?, ?, ?, ?)", [mapping.id, mapping.subject.type, mapping.subject.id, mapping.mapping_type, mapping.status, json(mapping.source), mapping.nutrition_per_100g ? json(mapping.nutrition_per_100g) : null]); + for (const collection of records("collections")) { + run("INSERT INTO collections VALUES (?, ?, ?, ?)", [collection.id, collection.name, collection.description ?? null, json(collection)]); + for (const [position, entry] of (collection.entries ?? []).entries()) run("INSERT INTO collection_recipes VALUES (?, ?, ?)", [collection.id, entry.recipe_id, position + 1]); + } + db.exec("COMMIT"); +} catch (error) { + db.exec("ROLLBACK"); + throw error; +} + +const counts = Object.fromEntries(["recipes", "ingredients", "recipe_items", "purchase_items", "equipment"].map((table) => [table, db.prepare(`SELECT count(*) AS count FROM ${table}`).get().count])); +console.log(`Synchronized ${databasePath}: ${Object.entries(counts).map(([name, count]) => `${count} ${name}`).join(", ")}`); +writeSiteProjection(db); +db.close(); diff --git a/scripts/lib/migrations.d.mts b/scripts/lib/migrations.d.mts new file mode 100644 index 0000000..5aaf201 --- /dev/null +++ b/scripts/lib/migrations.d.mts @@ -0,0 +1,3 @@ +import type { DatabaseSync } from "node:sqlite"; + +export function applyMigrations(database: DatabaseSync, options?: { migrationsDirectory?: string }): string[]; diff --git a/scripts/lib/migrations.mjs b/scripts/lib/migrations.mjs new file mode 100644 index 0000000..8aa6904 --- /dev/null +++ b/scripts/lib/migrations.mjs @@ -0,0 +1,24 @@ +import fs from "node:fs"; +import path from "node:path"; + +export function applyMigrations(database, options = {}) { + const migrationsDirectory = options.migrationsDirectory ?? path.resolve(process.cwd(), "migrations"); + const names = fs.readdirSync(migrationsDirectory).filter((name) => /^\d+.*\.sql$/.test(name)).sort((left, right) => Number(left.match(/^\d+/)[0]) - Number(right.match(/^\d+/)[0])); + database.exec("CREATE TABLE IF NOT EXISTS schema_migrations (version INTEGER PRIMARY KEY, name TEXT NOT NULL, applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP)"); + const applied = []; + for (const name of names) { + const version = Number(name.match(/^\d+/)[0]); + if (database.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version)) continue; + database.exec("BEGIN IMMEDIATE"); + try { + database.exec(fs.readFileSync(path.join(migrationsDirectory, name), "utf8")); + database.prepare("INSERT INTO schema_migrations(version, name) VALUES (?, ?)").run(version, name); + database.exec("COMMIT"); + applied.push(name); + } catch (error) { + database.exec("ROLLBACK"); + throw new Error(`Failed database migration ${name}`, { cause: error }); + } + } + return applied; +} diff --git a/scripts/lib/site-projection.d.mts b/scripts/lib/site-projection.d.mts new file mode 100644 index 0000000..30265e4 --- /dev/null +++ b/scripts/lib/site-projection.d.mts @@ -0,0 +1,3 @@ +import type { DatabaseSync } from "node:sqlite"; +export function createSiteProjection(database: DatabaseSync): Record; +export function writeSiteProjection(database: DatabaseSync, target?: string): string; diff --git a/scripts/lib/site-projection.mjs b/scripts/lib/site-projection.mjs new file mode 100644 index 0000000..6252b59 --- /dev/null +++ b/scripts/lib/site-projection.mjs @@ -0,0 +1,53 @@ +import fs from "node:fs"; +import path from "node:path"; + +const json = (value, fallback) => { try { return JSON.parse(value); } catch { return fallback; } }; + +export function createSiteProjection(database) { + const units = database.prepare("SELECT * FROM units ORDER BY id").all().map((row) => ({ schema_version:2,id:row.id,name:row.name,symbol:row.symbol,dimension:row.dimension,system:row.system,...(row.base_unit_id?{base_conversion:{base_unit_id:row.base_unit_id,factor:row.factor,...(row.offset!=null?{offset:row.offset}:{})}}:{}) })); + const aliasQuery=database.prepare("SELECT name,kind FROM ingredient_aliases WHERE ingredient_id=? ORDER BY name"); + const densityQuery=database.prepare("SELECT * FROM ingredient_density_measurements WHERE ingredient_id=? ORDER BY id"); + const conversionQuery=database.prepare("SELECT * FROM ingredient_measure_conversions WHERE ingredient_id=? ORDER BY id"); + const ingredientPrepQuery=database.prepare("SELECT action_id,yield_factor,notes FROM ingredient_prep_actions WHERE ingredient_id=? ORDER BY action_id"); + const mappingIdsQuery=database.prepare("SELECT id,mapping_type FROM source_mappings WHERE subject_type='ingredient' AND subject_id=? AND status='reviewed' ORDER BY id"); + const ingredients = database.prepare("SELECT * FROM ingredients ORDER BY id").all().map((row) => { + const mappings=mappingIdsQuery.all(row.id), source=json(row.source_json,"{}"); + return { schema_version:row.schema_version,id:row.id,name:row.name,...(row.description?{description:row.description}:{}),status:row.status,categories:json(row.categories_json,[]),tags:json(row.tags_json,[]), + aliases:aliasQuery.all(row.id), + density_measurements:densityQuery.all(row.id).map((value)=>({id:value.id,mass:{quantity:value.mass_quantity,unit_id:value.mass_unit_id},volume:{quantity:value.volume_quantity,unit_id:value.volume_unit_id},...(value.temperature_c!=null?{temperature_c:value.temperature_c}:{}),...(value.state?{state:value.state}:{}),source:json(value.source_json,{})})), + measure_conversions:conversionQuery.all(row.id).map((value)=>({id:value.id,from:{quantity:value.from_quantity,unit_id:value.from_unit_id},to:{quantity:value.to_quantity,unit_id:value.to_unit_id},...(value.state?{state:value.state}:{}),source:json(value.source_json,{})})), + prep_actions:ingredientPrepQuery.all(row.id).map((value)=>({action_id:value.action_id,yield_factor:value.yield_factor,...(value.notes?{notes:value.notes}:{})})), + nutrition_mapping_ids:mappings.filter((value)=>value.mapping_type==="nutrition").map((value)=>value.id),allergen_mapping_ids:mappings.filter((value)=>value.mapping_type==="allergen").map((value)=>value.id), + ...(source.shelf_life?{shelf_life:source.shelf_life}:{}) }; + }); + const equipment = database.prepare("SELECT * FROM equipment ORDER BY id").all().map((row)=>({schema_version:2,id:row.id,name:row.name,...(row.category?{category:row.category}:{}),...(row.notes?{notes:row.notes}:{})})); + const prepActions = database.prepare("SELECT * FROM prep_actions ORDER BY id").all().map((row)=>({schema_version:2,id:row.id,name:row.name,action_type:row.action_type,...(row.default_yield_factor!=null?{default_yield_factor:row.default_yield_factor}:{}),...(row.notes?{notes:row.notes}:{})})); + const priceQuery=database.prepare("SELECT * FROM price_observations WHERE purchase_item_id=? ORDER BY effective_at,currency"); + const purchaseItems = database.prepare("SELECT * FROM purchase_items ORDER BY id").all().map((row)=>({schema_version:2,id:row.id,ingredient_id:row.ingredient_id,name:row.name,...(row.brand?{brand:row.brand}:{}),...(row.supplier_id?{supplier_id:row.supplier_id}:{}),...(row.supplier_sku?{supplier_sku:row.supplier_sku}:{}),status:row.status,package:{quantity:row.package_quantity,unit_id:row.package_unit_id,units_per_case:row.units_per_case,usable_yield_factor:row.usable_yield_factor},prices:priceQuery.all(row.id).map((price)=>({amount:price.amount,currency:price.currency,effective_at:price.effective_at,source:json(price.source_json,{})}))})); + const sourceMappings = database.prepare("SELECT * FROM source_mappings ORDER BY id").all().map((row)=>({schema_version:2,id:row.id,subject:{type:row.subject_type,id:row.subject_id},mapping_type:row.mapping_type,status:row.status,source:json(row.source_json,{}),...(row.nutrition_json?{nutrition_per_100g:json(row.nutrition_json,{})}:{})})); + const componentQuery=database.prepare("SELECT * FROM recipe_components WHERE recipe_id=? ORDER BY position"); + const itemQuery=database.prepare("SELECT * FROM recipe_items WHERE recipe_id=? AND component_id=? ORDER BY position"); + const itemPrepQuery=database.prepare("SELECT action_id,yield_factor,notes FROM item_prep_actions WHERE recipe_id=? AND item_id=? ORDER BY position"); + const stepQuery=database.prepare("SELECT * FROM recipe_steps WHERE recipe_id=? ORDER BY position"); + const stepEquipmentQuery=database.prepare("SELECT equipment_id FROM step_equipment WHERE recipe_id=? AND step_id=? ORDER BY equipment_id"); + const recipeEquipmentQuery=database.prepare("SELECT equipment_id FROM recipe_equipment WHERE recipe_id=? ORDER BY equipment_id"); + const recipeConversionQuery=database.prepare("SELECT * FROM recipe_measure_conversions WHERE recipe_id=? ORDER BY id"); + const recipes = database.prepare("SELECT * FROM recipes ORDER BY id").all().map((row)=>{ + const source=json(row.source_json,{}), oldComponents=new Map((source.components??[]).map((value)=>[value.id,value])), oldSteps=new Map((source.steps??[]).map((value)=>[value.id,value])); + const components=componentQuery.all(row.id).map((component)=>{const old=oldComponents.get(component.id)??{};return {...old,id:component.id,name:component.name,notes:json(component.notes_json,[]),items:itemQuery.all(row.id,component.id).map((item)=>({id:item.id,reference:item.ingredient_id?{ingredient_id:item.ingredient_id}:{recipe_id:item.subrecipe_id,...(item.subrecipe_revision!=null?{revision:item.subrecipe_revision}:{})},amount:{quantity:item.quantity,unit_id:item.unit_id},...(item.percentage!=null?{percentage:item.percentage}:{}),...(item.basis_member?{basis_member:true}:{}),...(item.optional?{optional:true}:{}),...(item.notes?{notes:item.notes}:{}),...(item.nutrition_retention_factor!==1?{nutrition_retention_factor:item.nutrition_retention_factor}:{}),...(itemPrepQuery.all(row.id,item.id).length?{prep:itemPrepQuery.all(row.id,item.id).map((prep)=>({action_id:prep.action_id,...(prep.yield_factor!=null?{yield_factor:prep.yield_factor}:{}),...(prep.notes?{notes:prep.notes}:{})}))}:{})}))};}); + const steps=stepQuery.all(row.id).map((step,index)=>{const old=oldSteps.get(step.id)??{},equipment_ids=stepEquipmentQuery.all(row.id,step.id).map((value)=>value.equipment_id);return {...old,id:step.id,order:index+1,instruction:step.instruction,...(step.critical_control_point?{critical_control_point:true}:{}),...(equipment_ids.length?{equipment_ids}:{})};}); + const equipment_ids=recipeEquipmentQuery.all(row.id).map((value)=>value.equipment_id); + source.measure_conversions=recipeConversionQuery.all(row.id).map((value)=>({id:value.id,from:{quantity:value.from_quantity,unit_id:value.from_unit_id},to:{quantity:value.to_quantity,unit_id:value.to_unit_id},...(value.notes?{notes:value.notes}:{}),source:json(value.source_json,{})})); + const scaling=row.scaling_mode?{mode:row.scaling_mode,...(row.scaling_basis_id?{basis_id:row.scaling_basis_id}:{}),...(row.scaling_basis_quantity!=null&&row.scaling_basis_unit_id?{basis_amount:{quantity:row.scaling_basis_quantity,unit_id:row.scaling_basis_unit_id}}:{})}:undefined; + return {...source,schema_version:row.schema_version,id:row.id,revision:row.revision,status:row.status,title:row.title,...(row.summary?{summary:row.summary}:{}),categories:json(row.categories_json,[]),tags:json(row.tags_json,[]),...(row.station?{station:row.station}:{}),...(row.auto_yield?{auto_yield:true}:{}),yield:{...(source.yield??{}),amount:{quantity:row.yield_quantity,unit_id:row.yield_unit_id},...(row.yield_servings!=null?{servings:row.yield_servings}:{}),...(row.yield_basis?{basis:row.yield_basis}:{})},...(scaling?{scaling}:{}),components,steps,notes:json(row.notes_json,[]),...(equipment_ids.length?{equipment_ids}:{})}; + }); + return { generated_at:new Date().toISOString(),units,ingredients,equipment,prepActions,purchaseItems,sourceMappings,recipes }; +} + +export function writeSiteProjection(database, target=path.resolve(process.cwd(),"generated","site-projection.json")) { + fs.mkdirSync(path.dirname(target),{recursive:true}); + const temporary=`${target}.tmp`; + fs.writeFileSync(temporary,`${JSON.stringify(createSiteProjection(database))}\n`); + fs.renameSync(temporary,target); + return target; +} diff --git a/scripts/receipt-products b/scripts/receipt-products new file mode 100755 index 0000000..615cb16 --- /dev/null +++ b/scripts/receipt-products @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Propose and apply purchasing items from the sibling ledger receipt archive.""" + +from __future__ import annotations + +import argparse, csv, datetime as dt, json, re +import xml.etree.ElementTree as ET +from pathlib import Path +from zipfile import ZipFile +import yaml + +ROOT = Path(__file__).resolve().parent.parent +LEDGER = ROOT.parent / "ledger" +NS = {"m": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} +FOOD_WORDS = set("flour milk cream cheese butter oil chicken beef pork bacon sugar salt pepper rice bean beans tomato sauce juice egg eggs yeast starch vinegar mayo mayonnaise syrup chocolate cocoa bread mozzarella parmesan shortening yogurt mustard garlic onion potato broccoli sausage honey walnut walnuts nuts oats vanilla fruit vegetable vegetables mushroom mushrooms pickle tortillas rolls ham turkey canola olive dough pasta spaghetti chips".split()) + +def slug(value): return re.sub(r"[^a-z0-9]+", "_", value.lower()).strip("_") +def tokens(value): return set(re.findall(r"[a-z0-9]+", value.lower())) + +def parse_package(name: str): + patterns = [ + (r"(?:^|[, ])(\d+(?:\.\d+)?)\s*(?:fl\.?\s*oz|fluid ounces?)\b", "fluid_ounce_us"), + (r"(?:^|[, ])(\d+(?:\.\d+)?)\s*(?:lb|lbs|pounds?)\b", "pound"), + (r"(?:^|[, ])(\d+(?:\.\d+)?)\s*(?:oz|ounces?)\b", "ounce_mass"), + (r"(?:^|[, ])(\d+(?:\.\d+)?)\s*(?:gal|gallon)\b", "gallon_us"), + (r"(?:^|[, ])(\d+(?:\.\d+)?)\s*(?:count|ct)\b", "each"), + ] + for pattern, unit in patterns: + match = re.search(pattern, name, re.I) + if match: return {"quantity": float(match.group(1)), "unit_id": unit} + return None + +def excel_date(value): + return (dt.datetime(1899, 12, 30) + dt.timedelta(days=float(value))).date().isoformat() + +def walmart_products(path: Path): + with ZipFile(path) as archive: root = ET.fromstring(archive.read("xl/worksheets/sheet2.xml")) + products = {} + for row in root.findall(".//m:row", NS)[2:]: + values=[] + for cell in row.findall("m:c", NS): + text=cell.find(".//m:t",NS); raw=cell.find("m:v",NS) + values.append(text.text if text is not None else raw.text if raw is not None else "") + if len(values)<7 or not values[5]: continue + date, _, name, quantity, price, product_id, url = values[:7] + record=products.setdefault(product_id,{"supplier_id":"walmart","supplier_sku":product_id,"name":name,"url":url,"package":parse_package(name),"prices":[]}) + record["prices"].append({"amount":float(price),"currency":"USD","effective_at":excel_date(date),"source":{"source_type":"supplier","url":values[7] if len(values)>7 else url,"title":"Walmart receipt","reviewed":True}}) + return list(products.values()) + +def sams_products(path: Path): + products={} + for row in csv.DictReader(path.open()): + sku=row["item_code"].strip(); name=row["description"].strip() + if not sku or "instant savings" in name.lower() or row.get("category")!="Expenses:Food:Groceries": continue + record=products.setdefault(sku,{"supplier_id":"sams_club","supplier_sku":sku,"name":name,"package":parse_package(name),"prices":[]}) + record["prices"].append({"amount":float(row["pre_tax_amount"]),"currency":"USD","effective_at":row["date"],"source":{"source_type":"supplier","title":"Sam's Club receipt","reviewed":True}}) + return list(products.values()) + +def score(name, ingredient): + query=tokens(ingredient["name"]); candidate=tokens(name) + aliases=[tokens(x["name"]) for x in ingredient.get("aliases",[])] + return max([len(query&candidate)/max(1,len(query)), *[len(a&candidate)/max(1,len(a)) for a in aliases]]) + +def propose(walmart: Path, sams: Path, output: Path): + ingredients=[yaml.safe_load(p.read_text()) for p in (ROOT/"culinary/ingredients").glob("*.yaml")] + products=[p for p in walmart_products(walmart)+sams_products(sams) if tokens(p["name"]) & FOOD_WORDS] + proposals=[] + for product in products: + ranked=sorted(((score(product["name"],i),i) for i in ingredients),key=lambda x:(-x[0],x[1]["name"]))[:5] + if ranked[0][0] < .5: continue + proposals.append({**product,"ingredient_candidates":[{"ingredient_id":i["id"],"name":i["name"],"score":round(s,3)} for s,i in ranked if s>0]}) + output.parent.mkdir(parents=True,exist_ok=True) + output.write_text(yaml.safe_dump({"generated_at":dt.datetime.now(dt.timezone.utc).isoformat(),"products":proposals},sort_keys=False)) + print(f"Wrote {len(proposals)} receipt product proposals to {output}") + +def apply(decisions_path: Path, candidates_path: Path): + decisions=json.loads(decisions_path.read_text())["decisions"] + products=yaml.safe_load(candidates_path.read_text())["products"] + by_key={f'{p["supplier_id"]}:{p["supplier_sku"]}':p for p in products} + target=ROOT/"culinary/purchase_items"; target.mkdir(exist_ok=True) + imported=skipped=0 + for key,ingredient_id in decisions.items(): + if ingredient_id is None: skipped+=1; continue + product=by_key.get(key) + if not product: raise SystemExit(f"Unknown receipt product {key}") + if not product.get("package"): + print(f"Skipped {key}: package size is not explicit"); skipped+=1; continue + item_id=f'{product["supplier_id"]}_{slug(product["supplier_sku"])}' + item={"schema_version":2,"id":item_id,"ingredient_id":ingredient_id,"name":product["name"],"supplier_id":product["supplier_id"],"supplier_sku":product["supplier_sku"],"status":"active","package":product["package"],"prices":product["prices"],"nutrition_mapping_ids":[],"allergen_mapping_ids":[]} + (target/f"{item_id}.yaml").write_text(yaml.safe_dump(item,sort_keys=False)); imported+=1 + print(f"Imported {imported} purchasing items; skipped {skipped}") + +def main(): + parser=argparse.ArgumentParser(description=__doc__); sub=parser.add_subparsers(dest="command",required=True) + p=sub.add_parser("propose"); p.add_argument("--walmart",type=Path,default=LEDGER/"documents/_inbox/walmart-receipts.xlsx"); p.add_argument("--sams",type=Path,default=LEDGER/"documents/merchants/sams-club/receipts/through-2026-07-29_sams-club_card-8766_receipt-items.csv"); p.add_argument("--output",type=Path,default=ROOT/"generated/receipt-product-candidates.yaml") + a=sub.add_parser("apply"); a.add_argument("decisions",type=Path); a.add_argument("--candidates",type=Path,default=ROOT/"generated/receipt-product-candidates.yaml") + args=parser.parse_args(); propose(args.walmart,args.sams,args.output) if args.command=="propose" else apply(args.decisions,args.candidates) +if __name__=="__main__": main() diff --git a/scripts/restart-app.mjs b/scripts/restart-app.mjs new file mode 100755 index 0000000..97e8d44 --- /dev/null +++ b/scripts/restart-app.mjs @@ -0,0 +1,51 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import { spawn } from "node:child_process"; + +const appPort = 4322; +const portHex = appPort.toString(16).toUpperCase().padStart(4, "0"); + +function listeningSocketInodes() { + const inodes = new Set(); + for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) { + if (!fs.existsSync(file)) continue; + for (const line of fs.readFileSync(file, "utf8").trim().split("\n").slice(1)) { + const columns = line.trim().split(/\s+/); + const localPort = columns[1]?.split(":").at(-1); + const state = columns[3]; + const inode = columns[9]; + if (localPort === portHex && state === "0A" && inode) inodes.add(inode); + } + } + return inodes; +} + +function listenerPids(inodes) { + const pids = []; + for (const entry of fs.readdirSync("/proc").filter((value) => /^\d+$/.test(value))) { + const directory = `/proc/${entry}/fd`; + let descriptors; + try { descriptors = fs.readdirSync(directory); } catch { continue; } + const ownsSocket = descriptors.some((descriptor) => { + try { + const target = fs.readlinkSync(`${directory}/${descriptor}`); + return [...inodes].some((inode) => target === `socket:[${inode}]`); + } catch { return false; } + }); + if (ownsSocket && Number(entry) !== process.pid) pids.push(Number(entry)); + } + return pids; +} + +const delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)); +const alive = (pid) => { try { process.kill(pid, 0); return true; } catch { return false; } }; + +const pids = listenerPids(listeningSocketInodes()); +for (const pid of pids) process.kill(pid, "SIGTERM"); +for (let attempt = 0; attempt < 20 && pids.some(alive); attempt += 1) await delay(100); +for (const pid of pids.filter(alive)) process.kill(pid, "SIGKILL"); + +const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm"; +const child = spawn(npmCommand, ["run", "dev:app"], { stdio: "inherit" }); +for (const signal of ["SIGINT", "SIGTERM"]) process.on(signal, () => child.kill(signal)); +child.on("exit", (code, signal) => process.exit(signal ? 1 : (code ?? 1))); diff --git a/scripts/site-project.mjs b/scripts/site-project.mjs new file mode 100644 index 0000000..61e28eb --- /dev/null +++ b/scripts/site-project.mjs @@ -0,0 +1,9 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import path from "node:path"; +import { DatabaseSync } from "node:sqlite"; +import { writeSiteProjection } from "./lib/site-projection.mjs"; +const databasePath=path.resolve(process.cwd(),"var","recipe-book.sqlite"); +if(!fs.existsSync(databasePath)) throw new Error(`Database does not exist: ${databasePath}`); +const database=new DatabaseSync(databasePath,{readOnly:true}); +try { console.log(`Projected site data to ${writeSiteProjection(database)}`); } finally { database.close(); } diff --git a/scripts/usda-fdc b/scripts/usda-fdc new file mode 100755 index 0000000..ff76949 --- /dev/null +++ b/scripts/usda-fdc @@ -0,0 +1,435 @@ +#!/usr/bin/env python3 +"""Search FoodData Central and import a provenance-preserving nutrition mapping.""" + +from __future__ import annotations + +import argparse +import datetime as dt +import difflib +import json +import os +import re +import time +import urllib.parse +import urllib.request +import urllib.error +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parent.parent +API = "https://api.nal.usda.gov/fdc/v1" +NUTRIENTS = { + "1008": "energy_kcal", + "2047": "energy_kcal", + "2048": "energy_kcal", + "1003": "protein_g", + "1004": "total_fat_g", + "1005": "carbohydrate_g", + "1079": "dietary_fiber_g", + "2000": "total_sugars_g", + "1093": "sodium_mg", + "1258": "saturated_fat_g", + "1253": "cholesterol_mg", + "1087": "calcium_mg", + "1089": "iron_mg", + "1092": "potassium_mg", + "1114": "vitamin_d_mcg", +} + + +def request(path: str, params: dict) -> dict: + key = os.environ.get("USDA_FDC_API_KEY") + if not key: + env_path = ROOT / ".env" + if env_path.exists(): + for line in env_path.read_text(encoding="utf-8").splitlines(): + name, separator, value = line.partition("=") + if separator and name.strip() == "USDA_FDC_API_KEY": + key = value.strip().strip("'\"") + break + key = key or "DEMO_KEY" + url = f"{API}/{path}?{urllib.parse.urlencode({**params, 'api_key': key})}" + with urllib.request.urlopen(url, timeout=30) as response: + return json.load(response) + + +def search(query: str, limit: int, data_types: str) -> None: + data = request("foods/search", {"query": query, "dataType": data_types, "pageSize": limit}) + for food in data.get("foods", []): + print(f"{food['fdcId']}\t{food['dataType']}\t{food['description']}") + + +def normalized_text(value: str) -> str: + return " ".join(re.findall(r"[a-z0-9]+", value.lower())) + + +def match_score(term: str, description: str) -> float: + query = normalized_text(term) + candidate = normalized_text(description) + query_tokens = set(query.split()) + candidate_tokens = set(candidate.split()) + if not query_tokens: + return 0 + recall = len(query_tokens & candidate_tokens) / len(query_tokens) + precision = len(query_tokens & candidate_tokens) / len(candidate_tokens) + score = 0.72 * recall + 0.18 * precision + 0.10 * difflib.SequenceMatcher(None, query, candidate).ratio() + head = normalized_text(description.split(",", 1)[0]) + if head == query: + score += 0.2 + elif query in candidate and not query_tokens.intersection(set(head.split())): + score -= 0.2 + return max(0, min(score, 1)) + + +def load_dataset(path: Path) -> list[dict]: + payload = json.loads(path.read_text(encoding="utf-8")) + return next(iter(payload.values())) + + +def propose(datasets: list[Path], output: Path, limit: int) -> None: + foods = [food for dataset in datasets for food in load_dataset(dataset) if isinstance(food, dict) and food.get("description")] + foods_by_id = {food["fdcId"]: food for food in foods} + recommendations_path = ROOT / "config" / "usda-review-recommendations.yaml" + recommendations = yaml.safe_load(recommendations_path.read_text()) if recommendations_path.exists() else {} + searchable = [(food, normalized_text(food["description"])) for food in foods] + proposals = [] + for ingredient_path in sorted((ROOT / "culinary" / "ingredients").glob("*.yaml")): + ingredient = yaml.safe_load(ingredient_path.read_text(encoding="utf-8")) + if ingredient.get("nutrition_mapping_ids"): + continue + terms = [ingredient["name"], *(alias["name"] for alias in ingredient.get("aliases", []))] + scored: list[tuple[float, dict]] = [] + for food, description in searchable: + score = max(match_score(term, food["description"]) for term in terms) + # Foundation records win close ties, without hiding the actual score. + rank = score + (0.015 if food.get("dataType") == "Foundation" else 0) + scored.append((rank, food)) + matches = sorted(scored, key=lambda item: (-item[0], item[1]["fdcId"]))[:limit] + recommended_id = recommendations.get(ingredient["id"]) + if recommended_id in foods_by_id and all(food["fdcId"] != recommended_id for _, food in matches): + matches.append((match_score(ingredient["name"], foods_by_id[recommended_id]["description"]), foods_by_id[recommended_id])) + proposals.append({ + "ingredient_id": ingredient["id"], + "ingredient_name": ingredient["name"], + "candidates": [ + { + "fdc_id": food["fdcId"], + "data_type": food["dataType"], + "description": food["description"], + "similarity": round(score - (0.015 if food.get("dataType") == "Foundation" else 0), 4), + } + for score, food in matches + ], + }) + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(yaml.safe_dump({"generated_at": dt.datetime.now(dt.timezone.utc).isoformat(), "candidates": proposals}, sort_keys=False), encoding="utf-8") + print(f"Wrote candidates for {len(proposals)} unmapped ingredients to {output}") + + +def normalized_nutrients(food: dict) -> dict[str, float]: + result: dict[str, float] = {} + for entry in food.get("foodNutrients", []): + nutrient = entry.get("nutrient", {}) + nutrient_id = str(nutrient.get("id", entry.get("nutrientId", ""))) + key = NUTRIENTS.get(nutrient_id) + amount = entry.get("amount") + if key and isinstance(amount, (int, float)): + # Foundation foods may expose multiple energy calculations. Prefer 2047, + # then 2048, over the older general energy entry 1008. + if key != "energy_kcal" or nutrient_id != "1008" or key not in result: + result[key] = amount + return dict(sorted(result.items())) + + +PORTION_UNITS = { + "cup": "cup_us", "tablespoon": "tablespoon_us", "tbsp": "tablespoon_us", + "teaspoon": "teaspoon_us", "tsp": "teaspoon_us", "milliliter": "milliliter", + "ml": "milliliter", "fluid ounce": "fluid_ounce_us", "fl oz": "fluid_ounce_us", +} +REJECTED_PORTION_WORDS = {"racc", "serving", "package", "container", "packet", "scoop"} + + +def normalized_portion(food: dict, portion: dict) -> dict | None: + amount, grams = portion.get("amount"), portion.get("gramWeight") + if not isinstance(amount, (int, float)) or amount <= 0 or not isinstance(grams, (int, float)) or grams <= 0: + return None + measure = portion.get("measureUnit") or {} + measure_name = str(measure.get("name") or measure.get("abbreviation") or "").strip().lower() + modifier = str(portion.get("modifier") or "").strip() + searchable = f"{measure_name} {modifier}".lower() + if any(re.search(rf"\b{word}\b", searchable) for word in REJECTED_PORTION_WORDS): + return None + unit_id, state = PORTION_UNITS.get(measure_name), modifier or None + if not unit_id: + patterns = [ + (r"^cups?\b", "cup_us"), (r"^(?:tablespoons?|tbsp)\b", "tablespoon_us"), + (r"^(?:teaspoons?|tsp)\b", "teaspoon_us"), (r"^(?:fluid ounces?|fl oz)\b", "fluid_ounce_us"), + ] + for pattern, candidate_unit in patterns: + match = re.match(pattern, modifier, re.IGNORECASE) + if match: + unit_id = candidate_unit + state = modifier[match.end():].lstrip(" ,-") or None + break + if not unit_id: + return None + fdc_id = int(food["fdcId"]) + portion_id = str(portion.get("id") or f"{unit_id}_{amount}_{grams}") + return { + "id": f"usda_{fdc_id}_{portion_id}", + "from": {"quantity": float(amount), "unit_id": unit_id}, + "to": {"quantity": float(grams), "unit_id": "gram"}, + **({"state": state} if state else {}), + "data_points": int(portion.get("dataPoints") or 0), + "source": { + "source_type": "usda_fdc", "external_id": str(fdc_id), + "url": f"https://fdc.nal.usda.gov/food-details/{fdc_id}/measures", + "title": food["description"], "publisher": "USDA Agricultural Research Service", + "retrieved_at": dt.date.today().isoformat(), "reviewed": False, + "notes": f"FoodData Central portion ID {portion_id}.", + }, + } + + +def mapped_usda_foods() -> list[tuple[str, int]]: + result = [] + for path in sorted((ROOT / "culinary" / "source_mappings").glob("*.yaml")): + mapping = yaml.safe_load(path.read_text(encoding="utf-8")) + source = mapping.get("source", {}) + subject = mapping.get("subject", {}) + if mapping.get("mapping_type") == "nutrition" and mapping.get("status") == "reviewed" and source.get("source_type") == "usda_fdc" and subject.get("type") == "ingredient": + result.append((subject["id"], int(source["external_id"]))) + return result + + +def propose_portions(output: Path, delay: float) -> None: + cache_dir = ROOT / "generated" / "usda-food-details" + cache_dir.mkdir(parents=True, exist_ok=True) + proposals = [] + mappings = mapped_usda_foods() + for index, (ingredient_id, fdc_id) in enumerate(mappings): + cache_path = cache_dir / f"{fdc_id}.json" + if cache_path.exists(): + food = json.loads(cache_path.read_text(encoding="utf-8")) + else: + try: + food = request(f"food/{fdc_id}", {}) + except urllib.error.HTTPError as error: + if error.code == 404: + print(f"Skipping unavailable FDC {fdc_id} mapped to {ingredient_id}") + continue + raise + cache_path.write_text(json.dumps(food), encoding="utf-8") + if index + 1 < len(mappings): + time.sleep(delay) + portions = [candidate for portion in food.get("foodPortions", []) if (candidate := normalized_portion(food, portion))] + if portions: + ingredient = yaml.safe_load((ROOT / "culinary" / "ingredients" / f"{ingredient_id}.yaml").read_text(encoding="utf-8")) + proposals.append({"ingredient_id": ingredient_id, "ingredient_name": ingredient["name"], "fdc_id": fdc_id, "food_description": food["description"], "portions": portions}) + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(yaml.safe_dump({"generated_at": dt.datetime.now(dt.timezone.utc).isoformat(), "proposals": proposals}, sort_keys=False), encoding="utf-8") + print(f"Wrote {sum(len(item['portions']) for item in proposals)} portion candidates for {len(proposals)} ingredients to {output}") + + +def apply_portions(selected: set[str]) -> None: + candidates_path = ROOT / "generated" / "usda-portion-candidates.yaml" + candidates = yaml.safe_load(candidates_path.read_text(encoding="utf-8"))["proposals"] + applied = 0 + for proposal in candidates: + ingredient_path = ROOT / "culinary" / "ingredients" / f"{proposal['ingredient_id']}.yaml" + ingredient = yaml.safe_load(ingredient_path.read_text(encoding="utf-8")) + conversions = [item for item in ingredient.get("measure_conversions", []) if not item["id"].startswith("usda_") or item["id"] in selected] + ingredient["measure_conversions"] = conversions + existing = {item["id"]: index for index, item in enumerate(conversions)} + for portion in proposal["portions"]: + if portion["id"] in selected: + portion = {key: value for key, value in portion.items() if key != "data_points"} + portion["source"]["reviewed"] = True + portion["source"]["reviewed_at"] = dt.date.today().isoformat() + if portion["id"] in existing: + conversions[existing[portion["id"]]] = portion + else: + conversions.append(portion); applied += 1 + if conversions: + ingredient_path.write_text(yaml.safe_dump(ingredient, sort_keys=False), encoding="utf-8") + print(f"Applied {applied} reviewed USDA portion equivalencies") + + +def apply_portion_decisions(path: Path) -> None: + payload = json.loads(path.read_text(encoding="utf-8")) + apply_portions(set(payload.get("accepted", []))) + + +def auto_apply_portions() -> None: + candidates_path = ROOT / "generated" / "usda-portion-candidates.yaml" + proposals = yaml.safe_load(candidates_path.read_text(encoding="utf-8"))["proposals"] + selected: set[str] = set() + for proposal in proposals: + # Keep preparation states distinct. For duplicate observations of the same + # unit and state, prefer USDA's largest underlying sample count. + best: dict[str, dict] = {} + for portion in proposal["portions"]: + key = portion["from"]["unit_id"] + current = best.get(key) + if current is None or portion.get("data_points", 0) > current.get("data_points", 0): + best[key] = portion + selected.update(portion["id"] for portion in best.values()) + apply_portions(selected) + + +def names_from_usda() -> None: + names: dict[str, str] = {} + for path in sorted((ROOT / "culinary" / "source_mappings").glob("*.yaml")): + mapping = yaml.safe_load(path.read_text(encoding="utf-8")) + source, subject = mapping.get("source", {}), mapping.get("subject", {}) + if mapping.get("mapping_type") == "nutrition" and mapping.get("status") == "reviewed" and source.get("source_type") == "usda_fdc" and subject.get("type") == "ingredient": + names[subject["id"]] = source["title"] + renamed = 0 + duplicates: dict[str, list[str]] = {} + for ingredient_id, usda_name in sorted(names.items()): + ingredient_path = ROOT / "culinary" / "ingredients" / f"{ingredient_id}.yaml" + ingredient = yaml.safe_load(ingredient_path.read_text(encoding="utf-8")) + for alias in ingredient.get("aliases", []): + if alias.get("kind") == "legacy": + alias["kind"] = "search" + old_name = ingredient["name"] + if old_name != usda_name: + aliases = ingredient.setdefault("aliases", []) + alias_names = {alias["name"].casefold() for alias in aliases} + if old_name.casefold() != usda_name.casefold() and old_name.casefold() not in alias_names: + aliases.append({"name": old_name, "kind": "search"}) + ingredient["name"] = usda_name + renamed += 1 + ingredient_path.write_text(yaml.safe_dump(ingredient, sort_keys=False), encoding="utf-8") + duplicates.setdefault(usda_name.casefold(), []).append(ingredient_id) + collisions = {name: ids for name, ids in duplicates.items() if len(ids) > 1} + print(f"Renamed {renamed} ingredients from {len(names)} reviewed USDA mappings; preserved old names as aliases") + for name, ids in sorted(collisions.items()): + print(f"Duplicate USDA name {name!r}: {', '.join(ids)}") + + +def import_food(ingredient_id: str, fdc_id: int, reviewed: bool, dataset: Path | None = None) -> None: + ingredient_path = ROOT / "culinary" / "ingredients" / f"{ingredient_id}.yaml" + if not ingredient_path.exists(): + raise SystemExit(f"Unknown ingredient: {ingredient_id}") + if dataset: + payload = json.loads(dataset.read_text(encoding="utf-8")) + foods = next(iter(payload.values())) + food = next((item for item in foods if item.get("fdcId") == fdc_id), None) + if not food: + raise SystemExit(f"FDC ID {fdc_id} not found in {dataset}") + else: + food = request(f"food/{fdc_id}", {}) + data_type = food.get("dataType") + allowed = {"Foundation", "SR Legacy", "FNDDS", "Branded", "Experimental"} + if data_type not in allowed: + raise SystemExit(f"Unsupported USDA data type: {data_type!r}") + mapping_id = f"usda_fdc_{ingredient_id}_{fdc_id}" + today = dt.date.today().isoformat() + mapping = { + "schema_version": 2, + "id": mapping_id, + "subject": {"type": "ingredient", "id": ingredient_id}, + "mapping_type": "nutrition", + "status": "reviewed" if reviewed else "candidate", + "source": { + "source_type": "usda_fdc", + "external_id": str(fdc_id), + "url": f"https://fdc.nal.usda.gov/food-details/{fdc_id}/nutrients", + "title": food["description"], + "publisher": "USDA Agricultural Research Service", + "retrieved_at": today, + "reviewed": reviewed, + **({"reviewed_at": today} if reviewed else {}), + }, + "usda": { + "fdc_id": fdc_id, + "data_type": data_type, + "description": food["description"], + **({"brand_owner": food["brandOwner"]} if food.get("brandOwner") else {}), + **({"gtin_upc": food["gtinUpc"]} if food.get("gtinUpc") else {}), + }, + "nutrition_per_100g": normalized_nutrients(food), + } + mapping_dir = ROOT / "culinary" / "source_mappings" + mapping_dir.mkdir(exist_ok=True) + mapping_path = mapping_dir / f"{mapping_id}.yaml" + mapping_path.write_text(yaml.safe_dump(mapping, sort_keys=False), encoding="utf-8") + + ingredient = yaml.safe_load(ingredient_path.read_text(encoding="utf-8")) + ids = ingredient.setdefault("nutrition_mapping_ids", []) + if mapping_id not in ids: + ids.append(mapping_id) + ingredient_path.write_text(yaml.safe_dump(ingredient, sort_keys=False), encoding="utf-8") + print(f"Imported {mapping_id} as {mapping['status']}: {food['description']}") + + +def apply_decisions(path: Path, reviewed: bool, delay: float, datasets: list[Path]) -> None: + payload = json.loads(path.read_text(encoding="utf-8")) + decisions = payload.get("decisions", {}) + if not isinstance(decisions, dict): + raise SystemExit("Decision file must contain a decisions object") + dataset_foods = {} + for dataset in datasets: + for food in load_dataset(dataset): + if isinstance(food, dict) and food.get("fdcId"): + dataset_foods[food["fdcId"]] = dataset + selected = [(ingredient_id, fdc_id) for ingredient_id, fdc_id in decisions.items() if isinstance(fdc_id, int)] + for index, (ingredient_id, fdc_id) in enumerate(selected): + import_food(ingredient_id, fdc_id, reviewed, dataset_foods.get(fdc_id)) + if index + 1 < len(selected) and fdc_id not in dataset_foods: + time.sleep(delay) + skipped = sum(fdc_id is None for fdc_id in decisions.values()) + print(f"Applied {len(selected)} selections; left {skipped} ingredients unmapped") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + sub = parser.add_subparsers(dest="command", required=True) + search_parser = sub.add_parser("search") + search_parser.add_argument("query") + search_parser.add_argument("--limit", type=int, default=10) + search_parser.add_argument("--data-types", default="Foundation,SR Legacy,FNDDS") + import_parser = sub.add_parser("import") + import_parser.add_argument("ingredient_id") + import_parser.add_argument("fdc_id", type=int) + import_parser.add_argument("--reviewed", action="store_true") + import_parser.add_argument("--dataset", type=Path, help="Official USDA JSON download (works without an API key)") + propose_parser = sub.add_parser("propose") + propose_parser.add_argument("--dataset", type=Path, action="append", required=True) + propose_parser.add_argument("--output", type=Path, default=ROOT / "generated" / "usda-candidates.yaml") + propose_parser.add_argument("--limit", type=int, default=5) + apply_parser = sub.add_parser("apply") + apply_parser.add_argument("decisions", type=Path) + apply_parser.add_argument("--reviewed", action="store_true") + apply_parser.add_argument("--delay", type=float, default=0.25, help="Seconds between API requests") + apply_parser.add_argument("--dataset", type=Path, action="append", default=[]) + portions_parser = sub.add_parser("portions", help="Fetch USDA portion-weight candidates for reviewed mappings") + portions_parser.add_argument("--output", type=Path, default=ROOT / "generated" / "usda-portion-candidates.yaml") + portions_parser.add_argument("--delay", type=float, default=0.1) + portions_apply_parser = sub.add_parser("portions-apply", help="Apply reviewed portion decisions") + portions_apply_parser.add_argument("decisions", type=Path) + sub.add_parser("portions-auto", help="Trust USDA portions and prefer the largest observation count") + sub.add_parser("names-from-usda", help="Use reviewed USDA descriptions as canonical ingredient names") + args = parser.parse_args() + if args.command == "search": + search(args.query, args.limit, args.data_types) + elif args.command == "import": + import_food(args.ingredient_id, args.fdc_id, args.reviewed, args.dataset) + elif args.command == "propose": + propose(args.dataset, args.output, args.limit) + elif args.command == "apply": + apply_decisions(args.decisions, args.reviewed, args.delay, args.dataset) + elif args.command == "portions": + propose_portions(args.output, args.delay) + elif args.command == "portions-apply": + apply_portion_decisions(args.decisions) + elif args.command == "portions-auto": + auto_apply_portions() + else: + names_from_usda() + + +if __name__ == "__main__": + main() diff --git a/scripts/validate-content b/scripts/validate-content new file mode 100755 index 0000000..f1f1e32 --- /dev/null +++ b/scripts/validate-content @@ -0,0 +1,253 @@ +#!/usr/bin/env python3 +"""Validate canonical culinary entities and their relationships.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +import yaml +from jsonschema import Draft202012Validator, FormatChecker +from referencing import Registry, Resource + + +ROOT = Path(__file__).resolve().parent.parent +SCHEMA_DIR = ROOT / "container/schemas" +CULINARY_DIR = ROOT / "culinary" + + +def load_yaml(path: Path, *, front_matter: bool = False): + text = path.read_text(encoding="utf-8") + if front_matter: + lines = text.splitlines() + if not lines or lines[0].strip() != "---": + raise ValueError("missing opening YAML front-matter delimiter") + try: + closing = next(i for i, line in enumerate(lines[1:], 1) if line.strip() == "---") + except StopIteration as exc: + raise ValueError("missing closing YAML front-matter delimiter") from exc + text = "\n".join(lines[1:closing]) + data = yaml.safe_load(text) + if not isinstance(data, dict): + raise ValueError("document must contain a YAML object") + return data + + +def format_path(parts) -> str: + return "".join(f"[{part}]" if isinstance(part, int) else f".{part}" for part in parts).lstrip(".") + + +def display_path(path: Path) -> Path: + try: + return path.relative_to(ROOT) + except ValueError: + return path + + +def main() -> int: + errors: list[str] = [] + def collect(paths, destination, validator, *, front_matter=False, id_matches_filename=False): + for path in paths: + relative = display_path(path) + try: + data = load_yaml(path, front_matter=front_matter) + except (OSError, ValueError, yaml.YAMLError) as exc: + errors.append(f"{relative}: {exc}") + continue + for issue in sorted(validator.iter_errors(data), key=lambda e: list(e.absolute_path)): + location = format_path(issue.absolute_path) + errors.append(f"{relative}{':' + location if location else ''}: {issue.message}") + item_id = data.get("id") + if not isinstance(item_id, str): + continue + if item_id in destination: + first = display_path(destination[item_id][0]) + errors.append(f"{relative}: duplicate id {item_id!r} (first defined in {first})") + else: + destination[item_id] = (path, data) + if id_matches_filename and path.stem != item_id: + errors.append(f"{relative}: filename must match id {item_id!r}") + + v2_specs = { + "units": "unit.schema.json", + "ingredients": "ingredient.schema.json", + "recipes": "recipe.schema.json", + "prep_actions": "prep-action.schema.json", + "allergens": "allergen.schema.json", + "source_mappings": "source-mapping.schema.json", + "suppliers": "supplier.schema.json", + "purchase_items": "purchase-item.schema.json", + "equipment": "equipment.schema.json", + "collections": "collection.schema.json", + "derived_recipes": "derived-recipe.schema.json", + } + v2_schema_dir = SCHEMA_DIR / "v2" + common_schema = json.loads((v2_schema_dir / "common.schema.json").read_text(encoding="utf-8")) + Draft202012Validator.check_schema(common_schema) + registry = Registry().with_resource( + common_schema["$id"], Resource.from_contents(common_schema) + ) + v2_entities: dict[str, dict[str, tuple[Path, dict]]] = {} + for entity_type, schema_name in v2_specs.items(): + schema_path = v2_schema_dir / schema_name + schema = json.loads(schema_path.read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + validator = Draft202012Validator( + schema, + registry=registry, + format_checker=FormatChecker(), + ) + destination: dict[str, tuple[Path, dict]] = {} + entity_dir = CULINARY_DIR / entity_type + paths = list(entity_dir.glob("*.yaml")) if entity_dir.exists() else [] + if paths: + collect( + sorted(paths), + destination, + validator, + id_matches_filename=entity_type != "derived_recipes", + ) + v2_entities[entity_type] = destination + + unit_ids = set(v2_entities["units"]) + unit_dimensions = { + unit_id: unit[1].get("dimension") for unit_id, unit in v2_entities["units"].items() + } + ingredient_ids = set(v2_entities["ingredients"]) + recipe_ids = set(v2_entities["recipes"]) + action_ids = set(v2_entities["prep_actions"]) + equipment_ids = set(v2_entities["equipment"]) + mapping_ids = set(v2_entities["source_mappings"]) + supplier_ids = set(v2_entities["suppliers"]) + + + def require_ref(path: Path, kind: str, item_id: str, known: set[str]): + if item_id not in known: + errors.append(f"{display_path(path)}: unknown v2 {kind} {item_id!r}") + + def check_amount(path: Path, amount): + if isinstance(amount, dict) and isinstance(amount.get("unit_id"), str): + require_ref(path, "unit_id", amount["unit_id"], unit_ids) + + def require_dimension(path: Path, amount, expected: str, context: str): + if not isinstance(amount, dict): + return + unit_id = amount.get("unit_id") + if unit_id in unit_dimensions and unit_dimensions[unit_id] != expected: + errors.append( + f"{display_path(path)}: {context} requires a {expected} unit, " + f"not {unit_id!r} ({unit_dimensions[unit_id]})" + ) + + for _, (path, unit) in v2_entities["units"].items(): + conversion = unit.get("base_conversion") + if conversion: + base_id = conversion["base_unit_id"] + require_ref(path, "base unit_id", base_id, unit_ids) + if base_id in unit_dimensions and unit_dimensions[base_id] != unit["dimension"]: + errors.append(f"{display_path(path)}: base unit must have the same dimension") + + for _, (path, ingredient) in v2_entities["ingredients"].items(): + for density in ingredient.get("density_measurements", []): + check_amount(path, density.get("mass")) + check_amount(path, density.get("volume")) + require_dimension(path, density.get("mass"), "mass", "density mass") + require_dimension(path, density.get("volume"), "volume", "density volume") + for conversion in ingredient.get("measure_conversions", []): + check_amount(path, conversion.get("from")) + check_amount(path, conversion.get("to")) + for mapping_id in ingredient.get("nutrition_mapping_ids", []) + ingredient.get("allergen_mapping_ids", []): + require_ref(path, "source mapping_id", mapping_id, mapping_ids) + for prep in ingredient.get("prep_actions", []): + require_ref(path, "prep action_id", prep["action_id"], action_ids) + + for mapping_id, (path, mapping) in v2_entities["source_mappings"].items(): + subject = mapping.get("subject", {}) + subject_type = subject.get("type") + subject_id = subject.get("id") + known_subjects = { + "ingredient": ingredient_ids, + "purchase_item": set(v2_entities["purchase_items"]), + "recipe": recipe_ids, + } + if subject_type in known_subjects: + require_ref(path, f"{subject_type} subject", subject_id, known_subjects[subject_type]) + if mapping.get("status") == "reviewed" and not mapping.get("source", {}).get("reviewed"): + errors.append(f"{display_path(path)}: reviewed mapping must have source.reviewed=true") + if subject_type == "ingredient" and subject_id in v2_entities["ingredients"]: + ingredient = v2_entities["ingredients"][subject_id][1] + field = "nutrition_mapping_ids" if mapping.get("mapping_type") == "nutrition" else "allergen_mapping_ids" + if mapping_id not in ingredient.get(field, []): + errors.append(f"{display_path(path)}: mapping is not referenced by ingredient {subject_id!r}") + + for _, (path, recipe) in v2_entities["recipes"].items(): + check_amount(path, recipe.get("yield", {}).get("amount")) + check_amount(path, recipe.get("yield", {}).get("serving_size")) + check_amount(path, recipe.get("scaling", {}).get("basis_amount")) + component_ids = {component.get("id") for component in recipe.get("components", [])} + if len(component_ids) != len(recipe.get("components", [])): + errors.append(f"{display_path(path)}: component IDs must be unique") + item_ids: set[str] = set() + for component in recipe.get("components", []): + check_amount(path, component.get("yield")) + for item in component.get("items", []): + item_id = item.get("id") + if item_id in item_ids: + errors.append(f"{display_path(path)}: component item ID {item_id!r} is duplicated") + item_ids.add(item_id) + check_amount(path, item.get("amount")) + reference = item.get("reference", {}) + if "ingredient_id" in reference: + require_ref(path, "ingredient_id", reference["ingredient_id"], ingredient_ids) + if "recipe_id" in reference: + require_ref(path, "recipe_id", reference["recipe_id"], recipe_ids) + for prep in item.get("prep", []): + require_ref(path, "prep action_id", prep["action_id"], action_ids) + orders = [step.get("order") for step in recipe.get("steps", [])] + if orders != list(range(1, len(orders) + 1)): + errors.append(f"{display_path(path)}: step order must be contiguous starting at 1") + step_ids = [step.get("id") for step in recipe.get("steps", [])] + if len(step_ids) != len(set(step_ids)): + errors.append(f"{display_path(path)}: step IDs must be unique") + for equipment_id in recipe.get("equipment_ids", []): + require_ref(path, "equipment_id", equipment_id, equipment_ids) + for step in recipe.get("steps", []): + check_amount(path, step.get("duration")) + check_amount(path, step.get("temperature")) + require_dimension(path, step.get("duration"), "time", "step duration") + require_dimension(path, step.get("temperature"), "temperature", "step temperature") + for component_id in step.get("component_ids", []): + if component_id not in component_ids: + errors.append(f"{display_path(path)}: step references unknown component_id {component_id!r}") + for item_id in step.get("item_ids", []): + if item_id not in item_ids: + errors.append(f"{display_path(path)}: step references unknown item_id {item_id!r}") + for equipment_id in step.get("equipment_ids", []): + require_ref(path, "equipment_id", equipment_id, equipment_ids) + + for _, (path, item) in v2_entities["purchase_items"].items(): + require_ref(path, "ingredient_id", item["ingredient_id"], ingredient_ids) + if "supplier_id" in item: + require_ref(path, "supplier_id", item["supplier_id"], supplier_ids) + require_ref(path, "package unit_id", item["package"]["unit_id"], unit_ids) + for mapping_id in item.get("nutrition_mapping_ids", []) + item.get("allergen_mapping_ids", []): + require_ref(path, "source mapping_id", mapping_id, mapping_ids) + + for _, (path, collection) in v2_entities["collections"].items(): + for entry in collection.get("entries", []): + require_ref(path, "recipe_id", entry["recipe_id"], recipe_ids) + + if errors: + print(f"Content validation failed with {len(errors)} error(s):", file=sys.stderr) + for error in errors: + print(f"- {error}", file=sys.stderr) + return 1 + + v2_count = sum(len(records) for records in v2_entities.values()) + print(f"Validated {v2_count} canonical culinary entities.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/application/pages/api/app/entities/delete.ts b/src/application/pages/api/app/entities/delete.ts new file mode 100644 index 0000000..d43576f --- /dev/null +++ b/src/application/pages/api/app/entities/delete.ts @@ -0,0 +1,34 @@ +import type { APIRoute } from "astro"; +import { openDatabase,refreshSiteProjection } from "../../../../../lib/database"; + +export const prerender=false; +const allowed=new Set(["recipe","ingredient","book","purchase"]); +export const POST:APIRoute=async({request})=>{ + const database=openDatabase({readOnly:false}); + if(!database)return Response.json({error:"Database unavailable."},{status:503}); + try { + const body=await request.json() as {type?:string;ids?:unknown}; + const type=String(body.type??""),ids=Array.isArray(body.ids)?[...new Set(body.ids.map(String).filter(Boolean))]:[]; + if(!allowed.has(type)||ids.length===0||ids.length>500)throw new Error("Invalid delete request."); + const placeholders=ids.map(()=>"?").join(","); + if(type==="ingredient"){ + const used=database.prepare(`SELECT DISTINCT i.name FROM ingredients i JOIN recipe_items r ON r.ingredient_id=i.id WHERE i.id IN (${placeholders}) ORDER BY i.name`).all(...ids) as Array<{name:string}>; + if(used.length)throw new Error(`Cannot delete ingredients used in recipes: ${used.map(x=>x.name).join(", ")}.`); + } + if(type==="recipe"){ + const used=database.prepare(`SELECT DISTINCT r.title FROM recipes r JOIN recipe_items i ON i.subrecipe_id=r.id WHERE r.id IN (${placeholders}) ORDER BY r.title`).all(...ids) as Array<{title:string}>; + if(used.length)throw new Error(`Cannot delete recipes used as sub-recipes: ${used.map(x=>x.title).join(", ")}.`); + } + database.exec("BEGIN IMMEDIATE"); + try { + if(type==="recipe")database.prepare(`UPDATE recipes SET deleted_at=CURRENT_TIMESTAMP,status='archived' WHERE id IN (${placeholders})`).run(...ids); + if(type==="ingredient")database.prepare(`UPDATE ingredients SET deleted_at=CURRENT_TIMESTAMP,status='archived' WHERE id IN (${placeholders})`).run(...ids); + if(type==="book")database.prepare(`UPDATE collections SET deleted_at=CURRENT_TIMESTAMP WHERE id IN (${placeholders})`).run(...ids); + if(type==="purchase")database.prepare(`DELETE FROM purchase_items WHERE id IN (${placeholders})`).run(...ids); + database.exec("COMMIT"); + }catch(cause){database.exec("ROLLBACK");throw cause;} + refreshSiteProjection(database); + return Response.json({deleted:ids.length}); + }catch(cause){return Response.json({error:cause instanceof Error?cause.message:"Unable to delete items."},{status:400});} + finally{database.close();} +}; diff --git a/src/application/pages/api/app/recipes/[id].ts b/src/application/pages/api/app/recipes/[id].ts new file mode 100644 index 0000000..5552810 --- /dev/null +++ b/src/application/pages/api/app/recipes/[id].ts @@ -0,0 +1,15 @@ +import type { APIRoute } from "astro"; +import { openDatabase, saveRecipeStructure, type RecipeStructure } from "../../../../../lib/database"; + +export const prerender = false; +export const POST: APIRoute = async ({ params, request }) => { + const database = openDatabase({ readOnly: false }); + if (!database) return Response.json({ error: "Database is unavailable." }, { status: 503 }); + try { + const structure = await request.json() as RecipeStructure; + const saved = saveRecipeStructure(database, params.id!, structure); + return Response.json(saved); + } catch (error) { + return Response.json({ error: error instanceof Error ? error.message : "Unable to save recipe." }, { status: 400 }); + } finally { database.close(); } +}; diff --git a/src/application/pages/app/archive.astro b/src/application/pages/app/archive.astro new file mode 100644 index 0000000..eebe4c8 --- /dev/null +++ b/src/application/pages/app/archive.astro @@ -0,0 +1,9 @@ +--- +export const prerender=false; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import {openDatabase,refreshSiteProjection} from "../../../lib/database"; +const database=openDatabase({readOnly:false});if(!database)return Astro.redirect("/app/",303); +if(Astro.request.method==="POST"){const form=await Astro.request.formData(),type=String(form.get("type")),id=String(form.get("id"));const tables:{[key:string]:string}={recipe:"recipes",ingredient:"ingredients",book:"collections"};if(tables[type])database.prepare(`UPDATE ${tables[type]} SET deleted_at=NULL${type!=="book"?",status='active'":""} WHERE id=?`).run(id);refreshSiteProjection(database);database.close();return Astro.redirect("/app/archive/",303);} +const items=[...(database.prepare("SELECT id,title name,deleted_at FROM recipes WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"recipe"})),...(database.prepare("SELECT id,name,deleted_at FROM ingredients WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"ingredient"})),...(database.prepare("SELECT id,name,deleted_at FROM collections WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"book"}))].sort((a,b)=>a.name.localeCompare(b.name));database.close(); +--- +
← All items

Archive

Restore recipes, ingredients, and recipe books removed from the active workspace.

{items.length?items.map(item=>
{item.type==="recipe"?"▦":item.type==="book"?"▣":"●"}{item.name}{item.type} · deleted {item.deleted_at}
):

Nothing has been archived.

}
diff --git a/src/application/pages/app/index.astro b/src/application/pages/app/index.astro new file mode 100644 index 0000000..49c72a8 --- /dev/null +++ b/src/application/pages/app/index.astro @@ -0,0 +1,92 @@ +--- +export const prerender = false; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import EntityDirectory from "../../../components/EntityDirectory"; +import { openDatabase } from "../../../lib/database"; + +const database = openDatabase(); +if (!database) return new Response("Database unavailable", { status:503 }); +const recipes=database.prepare(`SELECT r.id,r.title,r.status,r.revision,r.yield_quantity,r.yield_unit_id, + (SELECT count(*) FROM recipe_items ri WHERE ri.recipe_id=r.id) item_count, + (SELECT count(*) FROM recipe_steps rs WHERE rs.recipe_id=r.id AND rs.instruction LIKE 'TODO:%') placeholder_count + FROM recipes r WHERE r.deleted_at IS NULL ORDER BY r.title`).all() as any[]; +const ingredients=database.prepare(`SELECT i.id,i.name,i.status, + (SELECT count(*) FROM recipe_items r WHERE r.ingredient_id=i.id) recipe_count, + (SELECT count(*) FROM price_observations po JOIN purchase_items p ON p.id=po.purchase_item_id WHERE p.ingredient_id=i.id) price_count, + (SELECT count(*) FROM source_mappings m WHERE m.subject_type='ingredient' AND m.subject_id=i.id AND m.mapping_type='nutrition' AND m.status='reviewed') nutrition_count + FROM ingredients i WHERE i.deleted_at IS NULL ORDER BY i.name`).all() as any[]; +const books=database.prepare("SELECT c.id,c.name,c.description,(SELECT count(*) FROM collection_recipes r WHERE r.collection_id=c.id) recipe_count FROM collections c WHERE c.deleted_at IS NULL ORDER BY c.name").all() as any[]; +const purchases=database.prepare(`SELECT p.id,p.ingredient_id,p.name,p.supplier_id,p.status,i.name ingredient_name,p.package_quantity,p.package_unit_id, + (SELECT amount FROM price_observations x WHERE x.purchase_item_id=p.id ORDER BY effective_at DESC LIMIT 1) latest_price + FROM purchase_items p JOIN ingredients i ON i.id=p.ingredient_id ORDER BY p.name`).all() as any[]; +database.close(); + +const requested=Astro.url.searchParams.get("type")??"ingredient"; +const type=["recipe","ingredient","book","purchase"].includes(requested)?requested:"ingredient"; +const query=(Astro.url.searchParams.get("q")??"").trim(); +const normalizedQuery=query.toLocaleLowerCase(); +const validSearchTypes=["recipe","ingredient","book","purchase"]; +const selectedSearchTypes=Astro.url.searchParams.getAll("item_type").filter((value)=>validSearchTypes.includes(value)); +const filteringSearchTypes=selectedSearchTypes.length>0; +const attention=Astro.url.searchParams.get("attention")==="1", missingCost=Astro.url.searchParams.get("missing_cost")==="1", noUsda=Astro.url.searchParams.get("no_usda")==="1",unused=Astro.url.searchParams.get("unused")==="1",emptyRecipe=Astro.url.searchParams.get("empty_recipe")==="1",placeholderSteps=Astro.url.searchParams.get("placeholder_steps")==="1"; +const filtering=attention||missingCost||noUsda||unused||emptyRecipe||placeholderSteps; +const filteredIngredients=ingredients.filter((ingredient)=>{if(!filtering)return true;const selected=[missingCost&&ingredient.price_count===0,noUsda&&ingredient.nutrition_count===0,unused&&ingredient.recipe_count===0].filter(Boolean);return missingCost||noUsda||unused?selected.length>0:ingredient.price_count===0||ingredient.nutrition_count===0||ingredient.recipe_count===0;}); +const filteredRecipes=recipes.filter(recipe=>!filtering||(emptyRecipe&&recipe.item_count===0)||(placeholderSteps&&recipe.placeholder_count>0)||(!emptyRecipe&&!placeholderSteps&&(recipe.item_count===0||recipe.placeholder_count>0))); +const tabs=[ + {type:"recipe",label:"Recipes",count:recipes.length,icon:"▦",kind:"recipe"}, + {type:"ingredient",label:"Ingredients",count:ingredients.length,icon:"●",kind:"ingredient"}, + {type:"book",label:"Recipe books",count:books.length,icon:"▣",kind:"book"}, + {type:"purchase",label:"Purchase items",count:purchases.length,icon:"$",kind:"purchase"}, +]; +const allSearchResults=normalizedQuery ? [ + ...recipes.filter((item)=>`${item.title} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({kind:"recipe",label:"Recipe",icon:"▦",name:item.title,detail:`${item.yield_quantity} ${item.yield_unit_id}`,href:`/app/recipes/${item.id}/`})), + ...ingredients.filter((item)=>`${item.name} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({kind:"ingredient",label:"Ingredient",icon:"●",name:item.name,detail:`Used in ${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:`/app/ingredients/${item.id}/`})), + ...books.filter((item)=>`${item.name} ${item.description??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({kind:"book",label:"Recipe book",icon:"▣",name:item.name,detail:`${item.recipe_count} ${item.recipe_count===1?"recipe":"recipes"}`,href:"/app/?type=book"})), + ...purchases.filter((item)=>`${item.name} ${item.ingredient_name} ${item.supplier_id??""} ${item.id}`.toLocaleLowerCase().includes(normalizedQuery)).map((item)=>({kind:"purchase",label:"Purchase item",icon:"$",name:item.name,detail:item.ingredient_name,href:`/app/ingredients/${item.ingredient_id}/#costs`})), +].sort((a,b)=>a.name.localeCompare(b.name)):[]; +const searchResults=filteringSearchTypes?allSearchResults.filter((result)=>selectedSearchTypes.includes(result.kind)):allSearchResults; +const ingredientRows=filteredIngredients.map(item=>({id:item.id,name:item.name,href:`/app/ingredients/${item.id}/`,kind:"ingredient" as const,icon:"●"})); +const recipeRows=filteredRecipes.map(item=>({id:item.id,name:item.title,href:`/app/recipes/${item.id}/`,kind:"recipe" as const,icon:"▦"})); +const bookRows=books.map(item=>({id:item.id,name:item.name,href:`/app/recipe-books/${item.id}/`,kind:"book" as const,icon:"▣"})); +const purchaseRows=purchases.map(item=>({id:item.id,name:item.name,href:`/app/ingredients/${item.ingredient_id}/#costs`,kind:"purchase" as const,icon:"$"})); +--- +
+
+ +
+ ☷   Item type{filteringSearchTypes?` · ${selectedSearchTypes.length}`:""} +
+ + + + +
{filteringSearchTypes&&All types}
+
+
+
+ New + +
+
+ + {query?

{searchResults.length} {searchResults.length===1?"result":"results"} for “{query}”{filteringSearchTypes&&` · ${selectedSearchTypes.length} item ${selectedSearchTypes.length===1?"type":"types"}`}

{searchResults.length?:
No items of the selected types match this search.
}
:<> + {type==="ingredient"&&} + {type==="recipe"&&} + {type==="book"&&} + {type==="purchase"&&} + } +
diff --git a/src/application/pages/app/ingredients/[id].astro b/src/application/pages/app/ingredients/[id].astro new file mode 100644 index 0000000..4436d1c --- /dev/null +++ b/src/application/pages/app/ingredients/[id].astro @@ -0,0 +1,190 @@ +--- +export const prerender = false; +import BaseLayout from "../../../../layouts/BaseLayout.astro"; +import { openDatabase, refreshSiteProjection } from "../../../../lib/database"; +import { bestUsdaPortions, fetchUsdaFood, usdaNutrition } from "../../../../lib/usda"; +import { number } from "../../../../lib/format"; +import PurchaseItemForm from "../../../../components/PurchaseItemForm.astro"; +import DetailUtility from "../../../../components/DetailUtility.astro"; +const id = Astro.params.id!; +const editing = Astro.url.searchParams.get("edit") === "1"; +const database = openDatabase({ readOnly: false }); +if (!database) return Astro.redirect("/app/", 303); +let error: string | undefined; +let message = Astro.url.searchParams.get("message") ?? undefined; +if (Astro.request.method === "POST") { + try { + const form = await Astro.request.formData(); const intent = String(form.get("intent")); + if(intent==="merge"){ + const target=String(form.get("target_id")??"");if(!target||target===id||!database.prepare("SELECT 1 FROM ingredients WHERE id=? AND deleted_at IS NULL").get(target))throw new Error("Choose a valid target ingredient."); + database.exec("BEGIN IMMEDIATE");try{database.prepare("UPDATE recipe_items SET ingredient_id=? WHERE ingredient_id=?").run(target,id);database.prepare("UPDATE purchase_items SET ingredient_id=? WHERE ingredient_id=?").run(target,id);database.prepare("INSERT OR IGNORE INTO ingredient_aliases(ingredient_id,name,kind) SELECT ?,name,kind FROM ingredient_aliases WHERE ingredient_id=?").run(target,id);const sourceName=(database.prepare("SELECT name FROM ingredients WHERE id=?").get(id) as any).name;database.prepare("INSERT OR IGNORE INTO ingredient_aliases VALUES (?,?,'merged')").run(target,sourceName);database.prepare("UPDATE ingredients SET status='archived',deleted_at=CURRENT_TIMESTAMP WHERE id=?").run(id);database.exec("COMMIT");}catch(cause){database.exec("ROLLBACK");throw cause;} + refreshSiteProjection(database);database.close();return Astro.redirect(`/app/ingredients/${target}/?message=${encodeURIComponent("Ingredient merged")}`,303); + } + if (intent === "identity") { + const name=String(form.get("name")??"").trim(), status=String(form.get("status")??"active"); if(!name) throw new Error("Name is required."); + const uniqueValues=(values:string[])=>[...new Map(values.map(value=>[value.toLocaleLowerCase(),value])).values()]; + const tags=uniqueValues(String(form.get("tags")??"").split(",").map(x=>x.trim()).filter(Boolean)), aliases=uniqueValues(String(form.get("aliases")??"").split("\n").map(x=>x.trim()).filter(Boolean)), description=String(form.get("description")??"").trim(); + const prepValues=JSON.parse(String(form.get("prep_json")??"[]")) as Array<{action_id?:unknown;yield_percent?:unknown;notes?:unknown}>; if(!Array.isArray(prepValues))throw new Error("Prep actions are invalid."); + const knownActions=new Set((database.prepare("SELECT id FROM prep_actions").all() as any[]).map(row=>row.id)), seenActions=new Set(); + const normalizedPrep=prepValues.map((row)=>{const actionId=String(row.action_id??""),factor=Number(row.yield_percent)/100,notes=String(row.notes??"").trim()||null;if(!knownActions.has(actionId))throw new Error("A prep action is unknown.");if(seenActions.has(actionId))throw new Error("Each prep action can only appear once.");if(!(factor>0))throw new Error("Prep yield must be greater than 0%.");seenActions.add(actionId);return {actionId,factor,notes};}); + database.exec("BEGIN IMMEDIATE"); try { database.prepare("UPDATE ingredients SET name=?,status=?,description=?,tags_json=? WHERE id=?").run(name,status,description||null,JSON.stringify(tags),id); database.prepare("DELETE FROM ingredient_aliases WHERE ingredient_id=?").run(id); const insert=database.prepare("INSERT INTO ingredient_aliases(ingredient_id,name,kind) VALUES (?,?,'common')"); for(const alias of aliases) insert.run(id,alias); database.prepare("DELETE FROM ingredient_prep_actions WHERE ingredient_id=?").run(id); const insertPrep=database.prepare("INSERT INTO ingredient_prep_actions(ingredient_id,action_id,yield_factor,notes) VALUES (?,?,?,?)");for(const row of normalizedPrep)insertPrep.run(id,row.actionId,row.factor,row.notes); database.exec("COMMIT"); } catch(cause){database.exec("ROLLBACK");throw cause;} + refreshSiteProjection(database); database.close(); return Astro.redirect(`/app/ingredients/${id}/?message=Saved`,303); + } + if (intent === "conversion") { const fq=Number(form.get("from_quantity")),tq=Number(form.get("to_quantity")),requestedId=String(form.get("conversion_id")??"").trim(); if(!(fq>0&&tq>0)) throw new Error("Equivalency quantities must be positive."); const existing=requestedId?database.prepare("SELECT source_json FROM ingredient_measure_conversions WHERE ingredient_id=? AND id=?").get(id,requestedId) as any:undefined;if(requestedId&&(!existing||JSON.parse(existing.source_json).source_type!=="manual"))throw new Error("Only manual equivalencies can be edited."); const conversionId=requestedId||`manual_${Date.now()}`; database.prepare(`INSERT INTO ingredient_measure_conversions VALUES (?,?,?,?,?,?,?,?) ON CONFLICT(ingredient_id,id) DO UPDATE SET from_quantity=excluded.from_quantity,from_unit_id=excluded.from_unit_id,to_quantity=excluded.to_quantity,to_unit_id=excluded.to_unit_id,state=excluded.state,source_json=excluded.source_json`).run(id,conversionId,fq,String(form.get("from_unit_id")),tq,String(form.get("to_unit_id")),String(form.get("state")??"").trim()||null,JSON.stringify({source_type:"manual",title:"Recipe application",reviewed:true})); refreshSiteProjection(database); message=requestedId?"Equivalency updated":"Equivalency added"; } + if (intent === "delete_conversion") { const conversionId=String(form.get("conversion_id")??""),row=database.prepare("SELECT source_json FROM ingredient_measure_conversions WHERE ingredient_id=? AND id=?").get(id,conversionId) as any;if(!row||JSON.parse(row.source_json).source_type!=="manual")throw new Error("Only manual equivalencies can be removed.");database.prepare("DELETE FROM ingredient_measure_conversions WHERE ingredient_id=? AND id=?").run(id,conversionId);refreshSiteProjection(database);message="Equivalency removed"; } + if (intent === "purchase_item") { + const existingId=String(form.get("purchase_item_id")??"").trim(), name=String(form.get("name")??"").trim(), status=String(form.get("status")??"active"); + const packageQuantity=Number(form.get("package_quantity")), packageUnitId=String(form.get("package_unit_id")??""), unitsPerCase=Number(form.get("units_per_case")), usableYieldPercent=Number(form.get("usable_yield_percent")); + const price=Number(form.get("price")), currency=String(form.get("currency")??"USD").toUpperCase(), effectiveAt=String(form.get("effective_at")??""); + if(!name) throw new Error("Purchase item name is required."); + if(!["active","discontinued","unavailable"].includes(status)) throw new Error("Invalid purchase item status."); + if(!(packageQuantity>0)||!Number.isInteger(unitsPerCase)||unitsPerCase<1) throw new Error("Package quantity and units per case must be positive."); + if(!(usableYieldPercent>0&&usableYieldPercent<=100)) throw new Error("Usable yield must be greater than 0% and at most 100%."); + if(!(price>=0)||!/^[A-Z]{3}$/.test(currency)||!effectiveAt) throw new Error("Price, three-letter currency, and effective date are required."); + if(!database.prepare("SELECT 1 FROM units WHERE id=?").get(packageUnitId)) throw new Error("Unknown package unit."); + if(existingId&&!database.prepare("SELECT 1 FROM purchase_items WHERE id=? AND ingredient_id=?").get(existingId,id)) throw new Error("Purchase item does not belong to this ingredient."); + const purchaseId=existingId||`manual_${id}_${crypto.randomUUID().slice(0,8)}`; + database.exec("BEGIN IMMEDIATE"); + try { + database.prepare(`INSERT INTO purchase_items(id,ingredient_id,name,brand,supplier_id,supplier_sku,status,package_quantity,package_unit_id,units_per_case,usable_yield_factor) VALUES (?,?,?,?,?,?,?,?,?,?,?) + ON CONFLICT(id) DO UPDATE SET name=excluded.name,brand=excluded.brand,supplier_id=excluded.supplier_id,supplier_sku=excluded.supplier_sku,status=excluded.status,package_quantity=excluded.package_quantity,package_unit_id=excluded.package_unit_id,units_per_case=excluded.units_per_case,usable_yield_factor=excluded.usable_yield_factor`) + .run(purchaseId,id,name,String(form.get("brand")??"").trim()||null,String(form.get("supplier_id")??"").trim()||null,String(form.get("supplier_sku")??"").trim()||null,status,packageQuantity,packageUnitId,unitsPerCase,usableYieldPercent/100); + database.prepare("INSERT INTO price_observations VALUES (?,?,?,?,?) ON CONFLICT(purchase_item_id,effective_at,currency) DO UPDATE SET amount=excluded.amount,source_json=excluded.source_json") + .run(purchaseId,effectiveAt,currency,price,JSON.stringify({source_type:"manual",title:"Recipe application",reviewed:true})); + database.exec("COMMIT"); + } catch(cause) { database.exec("ROLLBACK"); throw cause; } + refreshSiteProjection(database); database.close(); return Astro.redirect(`/app/ingredients/${id}/?edit=1&message=${encodeURIComponent(existingId?"Purchase item and price updated":"Purchase item and price added")}#costs`,303); + } + if(intent==="delete_purchase_item"){ + const purchaseId=String(form.get("purchase_item_id")??"");if(!database.prepare("SELECT 1 FROM purchase_items WHERE id=? AND ingredient_id=?").get(purchaseId,id))throw new Error("Purchase item not found."); + database.prepare("DELETE FROM purchase_items WHERE id=? AND ingredient_id=?").run(purchaseId,id);refreshSiteProjection(database);database.close();return Astro.redirect(`/app/ingredients/${id}/?edit=1&message=${encodeURIComponent("Purchase item removed")}#costs`,303); + } + if (intent === "usda_mapping") { + const fdcId = String(form.get("fdc_id") ?? "").trim(); + if (!/^\d+$/.test(fdcId)) throw new Error("USDA FDC ID must contain digits only."); + const food = await fetchUsdaFood(fdcId, import.meta.env.USDA_FDC_API_KEY ?? ""); + const today = new Date().toISOString().slice(0,10), mappingId=`usda_fdc_${id}_${fdcId}`; + const source = { source_type:"usda_fdc",external_id:fdcId,url:`https://fdc.nal.usda.gov/food-details/${fdcId}/nutrients`,title:food.description,publisher:"USDA Agricultural Research Service",retrieved_at:today,reviewed:true,reviewed_at:today,notes:`FoodData Central data type: ${food.dataType}.` }; + const nutrition=usdaNutrition(food), portions=bestUsdaPortions(food), current=database.prepare("SELECT name,source_json FROM ingredients WHERE id=?").get(id) as any; + database.exec("BEGIN IMMEDIATE"); + try { + if(current.name!==food.description) database.prepare("INSERT OR IGNORE INTO ingredient_aliases(ingredient_id,name,kind) VALUES (?,?,'search')").run(id,current.name); + const canonical=JSON.parse(current.source_json); canonical.name=food.description; canonical.nutrition_mapping_ids=[mappingId]; + database.prepare("UPDATE ingredients SET name=?,source_json=? WHERE id=?").run(food.description,JSON.stringify(canonical),id); + database.prepare("DELETE FROM source_mappings WHERE subject_type='ingredient' AND subject_id=? AND mapping_type='nutrition'").run(id); + database.prepare("INSERT INTO source_mappings VALUES (?,?,?,?,?,?,?)").run(mappingId,"ingredient",id,"nutrition","reviewed",JSON.stringify(source),JSON.stringify(nutrition)); + for(const conversion of database.prepare("SELECT id,source_json FROM ingredient_measure_conversions WHERE ingredient_id=?").all(id) as any[]) if(JSON.parse(conversion.source_json).source_type==="usda_fdc") database.prepare("DELETE FROM ingredient_measure_conversions WHERE ingredient_id=? AND id=?").run(id,conversion.id); + const insert=database.prepare("INSERT INTO ingredient_measure_conversions VALUES (?,?,?,?,?,?,?,?)"); + for(const portion of portions) insert.run(id,portion.id,portion.from_quantity,portion.from_unit_id,portion.to_quantity,portion.to_unit_id,portion.state??null,JSON.stringify({...source,url:`https://fdc.nal.usda.gov/food-details/${fdcId}/measures`,notes:`FoodData Central portion ID ${portion.portion_id}.`})); + database.exec("COMMIT"); + } catch(cause) { database.exec("ROLLBACK"); throw cause; } + refreshSiteProjection(database); database.close(); return Astro.redirect(`/app/ingredients/${id}/?edit=1&message=${encodeURIComponent(`USDA mapping, nutrition, name, and ${portions.length} equivalencies updated`)}#nutrition`,303); + } + } catch(cause) { error=cause instanceof Error?cause.message:"Unable to save."; } +} +const ingredient = database.prepare("SELECT * FROM ingredients WHERE id=?").get(id) as any; +if(!ingredient){database.close();return new Response("Ingredient not found",{status:404});} +const ingredientTags=JSON.parse(ingredient.tags_json??"[]") as string[]; +const aliases=database.prepare("SELECT * FROM ingredient_aliases WHERE ingredient_id=? ORDER BY name").all(id) as any[]; +const prep=database.prepare("SELECT p.*,a.name FROM ingredient_prep_actions p JOIN prep_actions a ON a.id=p.action_id WHERE p.ingredient_id=? ORDER BY a.name").all(id) as any[]; +const actions=database.prepare("SELECT id,name FROM prep_actions ORDER BY name").all() as any[]; +const purchases=database.prepare("SELECT p.*,(SELECT amount FROM price_observations x WHERE x.purchase_item_id=p.id ORDER BY effective_at DESC LIMIT 1) latest_price,(SELECT currency FROM price_observations x WHERE x.purchase_item_id=p.id ORDER BY effective_at DESC LIMIT 1) latest_currency,(SELECT effective_at FROM price_observations x WHERE x.purchase_item_id=p.id ORDER BY effective_at DESC LIMIT 1) latest_date FROM purchase_items p WHERE ingredient_id=? ORDER BY name").all(id) as any[]; +const priceHistory=database.prepare("SELECT effective_at,currency,amount FROM price_observations WHERE purchase_item_id=? ORDER BY effective_at DESC,currency LIMIT 8"); +for(const purchase of purchases) purchase.prices=priceHistory.all(purchase.id); +const conversions=database.prepare("SELECT * FROM ingredient_measure_conversions WHERE ingredient_id=? ORDER BY id").all(id) as any[]; +const densities=database.prepare("SELECT * FROM ingredient_density_measurements WHERE ingredient_id=? ORDER BY id").all(id) as any[]; +const mappings=database.prepare("SELECT * FROM source_mappings WHERE subject_type='ingredient' AND subject_id=? AND mapping_type='nutrition' ORDER BY status,id").all(id) as any[]; +const nutrientLabels: Record = { + energy_kcal: ["Calories", "kcal"], protein_g: ["Protein", "g"], total_fat_g: ["Total fat", "g"], saturated_fat_g: ["Saturated fat", "g"], + carbohydrate_g: ["Carbohydrate", "g"], dietary_fiber_g: ["Dietary fiber", "g"], total_sugars_g: ["Total sugars", "g"], cholesterol_mg: ["Cholesterol", "mg"], + sodium_mg: ["Sodium", "mg"], potassium_mg: ["Potassium", "mg"], calcium_mg: ["Calcium", "mg"], iron_mg: ["Iron", "mg"], vitamin_d_mcg: ["Vitamin D", "mcg"], +}; +const nutritionMappings = mappings.map((mapping) => { + const source = JSON.parse(mapping.source_json); + const nutrition = JSON.parse(mapping.nutrition_json ?? "{}"); + const sourceUrl = source.url || (source.source_type === "usda_fdc" && source.external_id ? `https://fdc.nal.usda.gov/food-details/${source.external_id}/nutrients` : undefined); + return { ...mapping, source, sourceUrl, nutrients: Object.entries(nutrition).filter((entry): entry is [string, number] => typeof entry[1] === "number") as Array<[string, number]> }; +}); +const usdaMapping = nutritionMappings.find((mapping) => mapping.source.source_type === "usda_fdc"); +const usedIn=database.prepare("SELECT DISTINCT r.id,r.title,r.status FROM recipe_items i JOIN recipes r ON r.id=i.recipe_id WHERE i.ingredient_id=? ORDER BY r.title").all(id) as any[]; +const units=database.prepare("SELECT id,name,symbol,dimension FROM units ORDER BY dimension,name").all() as any[]; +const mergeCandidates=editing?database.prepare("SELECT id,name FROM ingredients WHERE id<>? AND deleted_at IS NULL ORDER BY name").all(id) as any[]:[]; +const unitById = new Map(units.map((unit) => [unit.id, unit])); +const conversionRows=conversions.map((row)=>{const source=JSON.parse(row.source_json??"{}");return {...row,source,isManual:source.source_type==="manual"};}); +const prepDisplay = prep.map((row) => { + const state = String(row.name).trim().toLowerCase(); + const measures: Array<{quantity:number;unit_id:string}> = []; + for (const conversion of conversions.filter((item) => String(item.state ?? "").trim().toLowerCase() === state)) { + measures.push({quantity:Number(conversion.from_quantity),unit_id:conversion.from_unit_id},{quantity:Number(conversion.to_quantity),unit_id:conversion.to_unit_id}); + } + for (const density of densities.filter((item) => String(item.state ?? "").trim().toLowerCase() === state)) { + measures.push({quantity:Number(density.mass_quantity),unit_id:density.mass_unit_id},{quantity:Number(density.volume_quantity),unit_id:density.volume_unit_id}); + } + const showMeasure = (dimension:string) => { + const measure=measures.find((item)=>unitById.get(item.unit_id)?.dimension===dimension); + return measure ? `${number(measure.quantity)} ${unitById.get(measure.unit_id)?.symbol ?? measure.unit_id}` : "—"; + }; + return {...row,weight:showMeasure("mass"),volume:showMeasure("volume"),each:showMeasure("count")}; +}); +database.close(); +--- + +
+ +

← Ingredients

{editing?:

{ingredient.name}

}
{editing?:✎ Edit}{editing&&
}
+ {message&&
{message}
}{error&&
{error}
} +
+
+ {editing&&
} +

Prep Actions

Any action taken on an ingredient that changes its yield or its weight-to-volume equivalency from the original raw state.

{editing?<>
{prepDisplay.map(x=>{[x.weight,x.volume,x.each].map(value=>)})}
Prep ActionYield %WeightVolumeEach
%

Use 100% for no change, 80% for trim or cooking loss, or 250% when cooking produces 2.5 times the original weight. Select Weight, Volume, or Each to define its equivalency.

:prep.length?{prepDisplay.map(x=>)}
Prep ActionYield %WeightVolumeEach
{x.name}{x.notes&&{x.notes}}{number(x.yield_factor*100)}%{x.weight}{x.volume}{x.each}
:

No prep actions defined.

}
+

Additional Details

{editing?
:<>
Recipes On {usedIn.length}{usedIn.length?:

This ingredient is not used by a recipe.

}
{ingredientTags.length>0&&
Tags{ingredientTags.map(tag=>{tag})}
}{ingredient.description&&
Description

{ingredient.description}

}
Ingredient aliases {aliases.length}{aliases.length?
    {aliases.map(x=>
  • {x.name}
  • )}
:

No aliases.

}
}
+
+ +
+
+{editing&&} + +
diff --git a/src/application/pages/app/ingredients/index.astro b/src/application/pages/app/ingredients/index.astro new file mode 100644 index 0000000..0085fdc --- /dev/null +++ b/src/application/pages/app/ingredients/index.astro @@ -0,0 +1,4 @@ +--- +export const prerender=false; +return Astro.redirect("/app/?type=ingredient",302); +--- diff --git a/src/application/pages/app/purchase-items/index.astro b/src/application/pages/app/purchase-items/index.astro new file mode 100644 index 0000000..8fd666c --- /dev/null +++ b/src/application/pages/app/purchase-items/index.astro @@ -0,0 +1,4 @@ +--- +export const prerender=false; +return Astro.redirect("/app/?type=purchase",302); +--- diff --git a/src/application/pages/app/quality.astro b/src/application/pages/app/quality.astro new file mode 100644 index 0000000..15e34e2 --- /dev/null +++ b/src/application/pages/app/quality.astro @@ -0,0 +1,10 @@ +--- +export const prerender = false; +import BaseLayout from "../../../layouts/BaseLayout.astro"; +import { openDatabase, recipeQualityRows } from "../../../lib/database"; +const database = openDatabase(); +const recipes = database ? recipeQualityRows(database) : []; +database?.close(); +const issues = recipes.map((recipe) => ({ ...recipe, issueCount: Number(recipe.yield_basis !== "measured") + Number(recipe.placeholder_steps > 0) + Number(recipe.equipment_count === 0) + Number(recipe.unpriced_items > 0) })).filter((recipe) => recipe.issueCount > 0).sort((a, b) => b.issueCount - a.issueCount || a.title.localeCompare(b.title)); +--- +

Management

Data quality

Recipes needing measured yields, prices, equipment, or complete methods.

{issues.map((recipe) => )}
RecipeYieldPricingEquipmentMethod
{recipe.title}{recipe.yield_basis ?? "Missing"}{recipe.unpriced_items ? `${recipe.unpriced_items} unpriced` : "Complete"}{recipe.equipment_count || "None"}{recipe.placeholder_steps ? "Placeholder" : "Present"}
diff --git a/src/application/pages/app/recipe-books/[id].astro b/src/application/pages/app/recipe-books/[id].astro new file mode 100644 index 0000000..55f5247 --- /dev/null +++ b/src/application/pages/app/recipe-books/[id].astro @@ -0,0 +1,18 @@ +--- +export const prerender=false; +import BaseLayout from "../../../../layouts/BaseLayout.astro"; +import DetailUtility from "../../../../components/DetailUtility.astro"; +import {openDatabase,refreshSiteProjection} from "../../../../lib/database"; +const id=Astro.params.id!,editing=Astro.url.searchParams.get("edit")==="1"; +const database=openDatabase({readOnly:false});if(!database)return Astro.redirect("/app/?error=database-missing",303); +let error=""; +if(Astro.request.method==="POST")try{const form=await Astro.request.formData(),intent=String(form.get("intent")); + if(intent==="details"){const name=String(form.get("name")??"").trim();if(!name)throw new Error("Name is required.");database.prepare("UPDATE collections SET name=?,description=? WHERE id=?").run(name,String(form.get("description")??"").trim()||null,id);} + if(intent==="membership"){const selected=new Set(form.getAll("recipe_id").map(String));database.exec("BEGIN IMMEDIATE");try{database.prepare("DELETE FROM collection_recipes WHERE collection_id=?").run(id);const insert=database.prepare("INSERT INTO collection_recipes(collection_id,recipe_id,position) VALUES (?,?,?)");[...selected].forEach((recipeId,index)=>insert.run(id,recipeId,index+1));database.exec("COMMIT");}catch(cause){database.exec("ROLLBACK");throw cause;}} + refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipe-books/${id}/`,303); +}catch(cause){error=cause instanceof Error?cause.message:"Unable to save recipe book.";} +const book=database.prepare("SELECT * FROM collections WHERE id=? AND deleted_at IS NULL").get(id) as any;if(!book){database.close();return new Response("Recipe book not found",{status:404});} +const recipes=database.prepare("SELECT r.id,r.title,r.status,cr.position,cr.recipe_id IS NOT NULL included FROM recipes r LEFT JOIN collection_recipes cr ON cr.recipe_id=r.id AND cr.collection_id=? WHERE r.deleted_at IS NULL ORDER BY coalesce(cr.position,999999),r.title").all(id) as any[]; +database.close(); +--- +

← Recipe books

{book.name}

{recipes.filter(x=>x.included).length} recipes

{editing?"✓ Done":"✎ Edit"}
{error&&

{error}

}
{editing&&
}

Recipes

{editing?"Choose the recipes included in this book.":book.description}

{editing&&}
{recipes.filter(recipe=>editing||recipe.included).map(recipe=>)}
diff --git a/src/application/pages/app/recipe-books/index.astro b/src/application/pages/app/recipe-books/index.astro new file mode 100644 index 0000000..5564f39 --- /dev/null +++ b/src/application/pages/app/recipe-books/index.astro @@ -0,0 +1,4 @@ +--- +export const prerender=false; +return Astro.redirect("/app/?type=book",302); +--- diff --git a/src/application/pages/app/recipe-books/new.astro b/src/application/pages/app/recipe-books/new.astro new file mode 100644 index 0000000..e9b3d84 --- /dev/null +++ b/src/application/pages/app/recipe-books/new.astro @@ -0,0 +1,8 @@ +--- +export const prerender=false; +import BaseLayout from "../../../../layouts/BaseLayout.astro"; +import { openDatabase,refreshSiteProjection } from "../../../../lib/database"; +let error:string|undefined; +if(Astro.request.method==="POST"){const database=openDatabase({readOnly:false});if(!database)return Astro.redirect("/app/?error=database-missing",303);try{const form=await Astro.request.formData();const name=String(form.get("name")??"").trim();const description=String(form.get("description")??"").trim()||null;if(!name)throw new Error("Name is required.");const base=name.toLocaleLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")||"recipe_book";let id=base,suffix=2;while(database.prepare("SELECT 1 FROM collections WHERE id=?").get(id))id=`${base}_${suffix++}`;database.prepare("INSERT INTO collections(id,name,description,source_json) VALUES (?,?,?,'{}')").run(id,name,description);refreshSiteProjection(database);database.close();return Astro.redirect("/app/?type=book",303);}catch(cause){error=cause instanceof Error?cause.message:"Unable to create recipe book.";database.close();}} +--- +

Recipe books

New recipe book

Create a collection for organizing recipes.

Recipe book details{error&&
{error}
}
Cancel
diff --git a/src/application/pages/app/recipes/[id].astro b/src/application/pages/app/recipes/[id].astro new file mode 100644 index 0000000..a03391d --- /dev/null +++ b/src/application/pages/app/recipes/[id].astro @@ -0,0 +1,186 @@ +--- +export const prerender = false; +import BaseLayout from "../../../../layouts/BaseLayout.astro"; +import { databaseProjection, duplicateRecipe, editableRecipe, openDatabase, refreshSiteProjection, saveRecipeMetadata } from "../../../../lib/database"; +import { recipeStructure } from "../../../../lib/database"; +import RecipeStructureEditor from "../../../../components/RecipeStructureEditor"; +import RecipeCalculator, { LiveCostValues, LiveNutritionValues } from "../../../../components/RecipeCalculator"; +import { calculateNutrition } from "../../../../lib/nutrition"; +import { calculateCost } from "../../../../lib/costing"; +import type { Ingredient, PrepAction, PurchaseItem, Recipe, SourceMapping, Unit } from "../../../../lib/types"; +import DetailUtility from "../../../../components/DetailUtility.astro"; +import { convertWithIngredientMeasures } from "../../../../lib/measurement"; + +const id = Astro.params.id!; +const editing = Astro.url.searchParams.get("edit") === "1"; +const database = openDatabase({ readOnly: false }); +if (!database) return Astro.redirect("/app/?error=database-missing", 303); +let error: string | undefined; + +if (Astro.request.method === "POST") { + try { + const form = await Astro.request.formData(); + if(form.get("intent")==="media"){ + const url=String(form.get("url")??"").trim(),mediaType=String(form.get("media_type")??"image"),stepId=String(form.get("step_id")??"").trim()||null;if(!url)throw new Error("Media URL is required.");if(!["image","video"].includes(mediaType))throw new Error("Invalid media type."); + const position=(database.prepare("SELECT coalesce(max(position),0)+1 position FROM recipe_media WHERE recipe_id=?").get(id) as any).position;database.prepare("INSERT INTO recipe_media(recipe_id,id,step_id,media_type,url,caption,position) VALUES (?,?,?,?,?,?,?)").run(id,`media_${Date.now()}`,stepId,mediaType,url,String(form.get("caption")??"").trim()||null,position);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1#additional`,303); + } + if(form.get("intent")==="additional"){ + const row=database.prepare("SELECT source_json FROM recipes WHERE id=?").get(id) as any,source=JSON.parse(row.source_json??"{}"); + const shelfQuantity=Number(form.get("shelf_quantity")),shelfUnit=String(form.get("shelf_unit")??"").trim(); + if(shelfQuantity>0&&shelfUnit)source.shelf_life={duration:{quantity:shelfQuantity,unit_id:shelfUnit},storage_condition:String(form.get("storage_condition")??"").trim()||undefined};else delete source.shelf_life; + const notes=String(form.get("notes")??"").split("\n").map(value=>value.trim()).filter(Boolean); + database.prepare("UPDATE recipes SET station=?,cover_media_url=?,notes_json=?,source_json=? WHERE id=?").run(String(form.get("station")??"").trim()||null,String(form.get("cover_media_url")??"").trim()||null,JSON.stringify(notes),JSON.stringify(source),id); + refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1#additional`,303); + } + if (form.get("intent") === "duplicate") { + const duplicateId = duplicateRecipe(database, id); + database.close(); + return Astro.redirect(`/app/recipes/${duplicateId}/?edit=1`, 303); + } + if(form.get("intent")==="auto_yield"){ + const current=editableRecipe(database,id);if(!current)throw new Error("Recipe not found."); + const autoRow=database.prepare("SELECT auto_yield,source_json FROM recipes WHERE id=?").get(id) as {auto_yield:number;source_json:string}; + const source=JSON.parse(autoRow.source_json??"{}"); + if(autoRow.auto_yield){ + const original=source.auto_yield_original; + if(original?.quantity>0&&original?.unit_id)saveRecipeMetadata(database,id,current.revision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:original.quantity,yield_unit_id:original.unit_id,yield_servings:current.yield_servings,yield_basis:original.basis??null}); + delete source.auto_yield_original;database.prepare("UPDATE recipes SET auto_yield=0,source_json=? WHERE id=?").run(JSON.stringify(source),id);refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1&saved=1`,303); + } + const projectionNow=databaseProjection(database) as {recipes:Recipe[];ingredients:Ingredient[];units:Unit[];sourceMappings:SourceMapping[]}; + const recipesNow=new Map(projectionNow.recipes.map(value=>[value.id,value])),ingredientsNow=new Map(projectionNow.ingredients.map(value=>[value.id,value])),unitsNow=new Map(projectionNow.units.map(value=>[value.id,value])); + const autoRecipe=recipesNow.get(id)!;let calculatedYieldWeightG=0;const conversionFailures:string[]=[]; + for(const item of autoRecipe.components.flatMap(component=>component.items).filter(item=>!item.optional)){ + try{if("ingredient_id" in item.reference){const ingredient=ingredientsNow.get(item.reference.ingredient_id);if(!ingredient)throw new Error("ingredient not found");calculatedYieldWeightG+=convertWithIngredientMeasures(item.amount,"gram",ingredient,unitsNow).quantity;}else{const child=recipesNow.get(item.reference.recipe_id);if(!child)throw new Error("sub-recipe not found");calculatedYieldWeightG+=convertWithIngredientMeasures(item.amount,"gram",{schema_version:2,id:child.id,name:child.title,status:"active",categories:[],measure_conversions:child.measure_conversions},unitsNow).quantity;}}catch{conversionFailures.push("ingredient_id" in item.reference?ingredientsNow.get(item.reference.ingredient_id)?.name??item.reference.ingredient_id:recipesNow.get(item.reference.recipe_id)?.title??item.reference.recipe_id);} + } + if(conversionFailures.length)throw new Error(`Auto calculate total yield needs a weight equivalency for: ${conversionFailures.join(", ")}.`); + if(!(calculatedYieldWeightG>0))throw new Error("No convertible ingredient weights are available for automatic yield."); + source.auto_yield_original={quantity:current.yield_quantity,unit_id:current.yield_unit_id,basis:current.yield_basis}; + saveRecipeMetadata(database,id,current.revision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:calculatedYieldWeightG,yield_unit_id:"gram",yield_servings:current.yield_servings,yield_basis:"theoretical"}); + database.prepare("UPDATE recipes SET auto_yield=1,source_json=? WHERE id=?").run(JSON.stringify(source),id);refreshSiteProjection(database); + database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1&saved=1#nutrition`,303); + } + if (form.get("intent") === "nutrition_servings") { + const current=editableRecipe(database,id);if(!current)throw new Error("Recipe not found."); + const yieldServings=Number(form.get("yield_servings")); + if(!Number.isFinite(yieldServings)||yieldServings<=0)throw new Error("Servings must be greater than zero."); + const expectedRevision=Number(form.get("revision")); + saveRecipeMetadata(database,id,expectedRevision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:current.yield_quantity,yield_unit_id:current.yield_unit_id,yield_servings:yieldServings,yield_basis:current.yield_basis}); + database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1#nutrition`,303); + } + if (form.get("intent") === "conversion") { + const fromQuantity=Number(form.get("from_quantity")),toQuantity=Number(form.get("to_quantity")); + const fromUnitId=String(form.get("from_unit_id")??""),toUnitId=String(form.get("to_unit_id")??""); + if(!(fromQuantity>0&&toQuantity>0)) throw new Error("Equivalency quantities must be positive."); + if(!database.prepare("SELECT 1 FROM units WHERE id IN (?,?) HAVING count(*)=2").get(fromUnitId,toUnitId)) throw new Error("Unknown equivalency unit."); + database.prepare("INSERT INTO recipe_measure_conversions VALUES (?,?,?,?,?,?,?,?)").run(id,`manual_${Date.now()}`,fromQuantity,fromUnitId,toQuantity,toUnitId,String(form.get("notes")??"").trim()||null,JSON.stringify({source_type:"manual",title:"Recipe application",reviewed:true})); + database.close(); return Astro.redirect(`/app/recipes/${id}/?edit=1#equivalencies`,303); + } + const title = String(form.get("title") ?? "").trim(); + const status = String(form.get("status") ?? ""); + const yieldQuantity = Number(form.get("yield_quantity")); + const yieldUnitId = String(form.get("yield_unit_id") ?? ""); + const servingsText = String(form.get("yield_servings") ?? "").trim(); + const yieldServings = servingsText ? Number(servingsText) : null; + const yieldBasis = String(form.get("yield_basis") ?? "") || null; + const categories = String(form.get("categories") ?? "").split(",").map((value) => value.trim()).filter(Boolean); + const tags = String(form.get("tags") ?? "").split(",").map((value) => value.trim()).filter(Boolean); + if (!title) throw new Error("Title is required."); + if (!["draft", "testing", "active", "retired", "archived"].includes(status)) throw new Error("Invalid status."); + if (!Number.isFinite(yieldQuantity) || yieldQuantity <= 0) throw new Error("Yield must be greater than zero."); + if (yieldServings != null && (!Number.isFinite(yieldServings) || yieldServings <= 0)) throw new Error("Servings must be greater than zero."); + if (!database.prepare("SELECT 1 FROM units WHERE id = ?").get(yieldUnitId)) throw new Error("Unknown yield unit."); + const expectedRevision = Number(form.get("revision")); + if (!Number.isInteger(expectedRevision) || expectedRevision < 1) throw new Error("Invalid recipe revision."); + saveRecipeMetadata(database, id, expectedRevision, { + status, title, summary: String(form.get("summary") ?? "").trim() || null, + categories_json: JSON.stringify(categories), tags_json: JSON.stringify(tags), + yield_quantity: yieldQuantity, yield_unit_id: yieldUnitId, + yield_servings: yieldServings, yield_basis: yieldBasis, + }); + database.close(); + return Astro.redirect(`/app/recipes/${id}/?saved=1`, 303); + } catch (cause) { + error = cause instanceof Error ? cause.message : "Unable to save recipe."; + } +} + +const recipe = editableRecipe(database, id); +if (!recipe) { database.close(); return new Response("Recipe not found", { status: 404 }); } +const units = database.prepare("SELECT id, name, symbol, dimension FROM units ORDER BY dimension, name").all() as Array<{ id: string; name: string; symbol: string; dimension: string }>; +const history = database.prepare("SELECT revision, saved_at, change_summary FROM recipe_revisions WHERE recipe_id = ? ORDER BY revision DESC LIMIT 10").all(id) as Array<{ revision: number; saved_at: string; change_summary: string }>; +const structure = recipeStructure(database, id)!; +const autoYield=Boolean((database.prepare("SELECT auto_yield FROM recipes WHERE id=?").get(id) as {auto_yield:number}).auto_yield); +const ingredientOptions = database.prepare("SELECT id, name FROM ingredients WHERE status = 'active' ORDER BY name").all() as Array<{ id: string; name: string }>; +const recipeOptions = database.prepare("SELECT id, title AS name FROM recipes WHERE status NOT IN ('retired', 'archived') ORDER BY title").all() as Array<{ id: string; name: string }>; +const prepActionOptions = database.prepare("SELECT id, name FROM prep_actions ORDER BY name").all() as Array<{ id: string; name: string }>; +const recipeConversions=database.prepare("SELECT * FROM recipe_measure_conversions WHERE recipe_id=? ORDER BY id").all(id) as any[]; +const additional=database.prepare("SELECT station,cover_media_url,notes_json,source_json FROM recipes WHERE id=?").get(id) as any; +const additionalSource=JSON.parse(additional.source_json??"{}"),shelfLife=additionalSource.shelf_life; +const media=database.prepare("SELECT * FROM recipe_media WHERE recipe_id=? ORDER BY position").all(id) as any[]; +const projection = databaseProjection(database) as { recipes:Recipe[]; ingredients:Ingredient[]; units:Unit[]; sourceMappings:SourceMapping[]; purchaseItems:PurchaseItem[]; prepActions:PrepAction[] }; +const domainRecipe = projection.recipes.find((entry) => entry.id === id)!; +const recipeMap = new Map(projection.recipes.map((entry) => [entry.id, entry])); +const ingredientMap = new Map(projection.ingredients.map((entry) => [entry.id, entry])); +const unitMap = new Map(projection.units.map((entry) => [entry.id, entry])); +const nutrition = calculateNutrition(domainRecipe, { recipes:recipeMap, ingredients:ingredientMap, units:unitMap, mappings:new Map(projection.sourceMappings.map((entry) => [entry.id, entry])) }); +const cost = calculateCost(domainRecipe, { recipes:recipeMap, ingredients:ingredientMap, units:unitMap, purchaseItems:new Map(projection.purchaseItems.map((entry) => [entry.id, entry])), prepActions:new Map(projection.prepActions.map((entry) => [entry.id, entry])) }); +const calculatorComponents = domainRecipe.components.map((component) => ({ ...component, items:component.items.map((item) => { const ingredient="ingredient_id" in item.reference ? ingredientMap.get(item.reference.ingredient_id) : undefined; const child="recipe_id" in item.reference ? recipeMap.get(item.reference.recipe_id) : undefined; return { ...item, basisMember:item.basis_member, label:ingredient?.name ?? child?.title ?? "Unknown", href:ingredient ? `/app/ingredients/${ingredient.id}/` : child ? `/app/recipes/${child.id}/` : undefined, measureConversions:ingredient?.measure_conversions ?? child?.measure_conversions ?? [] }; }) })); +const percentSubjectEntries=domainRecipe.components.flatMap(component=>component.items).map(item=>{const ingredient="ingredient_id" in item.reference?ingredientMap.get(item.reference.ingredient_id):undefined,child="recipe_id" in item.reference?recipeMap.get(item.reference.recipe_id):undefined;return ingredient?[`ingredient:${ingredient.id}`,{key:`ingredient:${ingredient.id}`,value:ingredient}] as [string,{key:string,value:Ingredient|Recipe}]:[`recipe:${child?.id}`,{key:`recipe:${child?.id}`,value:child!}] as [string,{key:string,value:Ingredient|Recipe}];}); +const percentSubjects=[...new Map(percentSubjectEntries).values()]; +const weightRates=Object.fromEntries(percentSubjects.flatMap(subject=>projection.units.map(unit=>{try{return [`${subject.key}:${unit.id}`,convertWithIngredientMeasures({quantity:1,unit_id:unit.id},"gram",subject.value as Ingredient,unitMap).quantity];}catch{return [`${subject.key}:${unit.id}`,null];}}))); +const nutritionMappingMap=new Map(projection.sourceMappings.map(mapping=>[mapping.id,mapping])); +const nutritionIngredients=domainRecipe.components.flatMap(component=>component.items).filter(item=>!item.optional).map(item=>{ + if("ingredient_id" in item.reference){ + const ingredient=ingredientMap.get(item.reference.ingredient_id)!; + const mapping=(ingredient.nutrition_mapping_ids??[]).map(mappingId=>nutritionMappingMap.get(mappingId)).find(mapping=>mapping?.mapping_type==="nutrition"&&mapping.status==="reviewed"&&Object.keys(mapping.nutrition_per_100g??{}).length>0); + let weightG:number|undefined;try{weightG=convertWithIngredientMeasures(item.amount,"gram",ingredient,unitMap).quantity;}catch{} + return {id:item.id,name:ingredient.name,href:`/app/ingredients/${ingredient.id}/?edit=1#nutrition`,weightG,mapped:Boolean(mapping),source:mapping?.source.title,kind:"ingredient" as const}; + } + const child=recipeMap.get(item.reference.recipe_id)!; + const childNutrition=calculateNutrition(child,{recipes:recipeMap,ingredients:ingredientMap,units:unitMap,mappings:nutritionMappingMap}); + let weightG:number|undefined;try{weightG=convertWithIngredientMeasures(item.amount,"gram",{id:child.id,name:child.title,schema_version:2,status:"active",categories:[],measure_conversions:child.measure_conversions},unitMap).quantity;}catch{} + return {id:item.id,name:child.title,href:`/app/recipes/${child.id}/#nutrition`,weightG,mapped:childNutrition.completeness>=.999,source:`Sub-recipe · ${Math.round(childNutrition.completeness*100)}% mapped`,kind:"recipe" as const}; +}); +database.close(); +const categories = JSON.parse(recipe.categories_json).join(", "); +const tags = JSON.parse(recipe.tags_json).join(", "); +const saved = Astro.url.searchParams.get("saved") === "1"; +--- + +
+ +

← Recipes

{editing?:

{recipe.title}

}{!editing&&

{recipe.status} · Revision {recipe.revision}

}
{editing?:✎ Edit}
+
{editing?<>:<>}
+ {editing?<>
+
+ + {saved &&
Changes saved.
} + {error &&
{error}
} +
Finished Yield{autoYield&&Calculated from convertible ingredient quantities}
+ +
+
Auto calculate total yield{autoYield&&Revert to original and disable auto calculate}
+
+
+
+

UoM Equivalency

Define how this finished recipe converts between weight, volume, and portions.

{recipeConversions.map(x=>
{x.from_quantity} {x.from_unit_id}={x.to_quantity} {x.to_unit_id}{x.notes}
)}
=
+
+

Additional Details

Shelf Life
+
Revision history · {history.length}{history.length?
    {history.map(entry=>
  1. Revision {entry.revision}{entry.saved_at}{entry.change_summary}
  2. )}
:

No application edits yet.

}
:<>

Prep Method {domainRecipe.steps.length}

    {domainRecipe.steps.map(step=>
  1. {step.order}.{step.instruction}{media.filter(entry=>entry.step_id===step.id).map(entry=>
    {entry.media_type==="image"?{entry.caption??""}/:
    )}
  2. )}

UoM Equivalency

{recipeConversions.length?recipeConversions.map(x=>
{x.from_quantity} {x.from_unit_id}={x.to_quantity} {x.to_unit_id}{x.notes}
):

No recipe-level equivalencies have been defined.

}
{additional.cover_media_url&&
}

Additional details

{additional.station&&

Station{additional.station}

}{shelfLife&&

Shelf life{shelfLife.duration.quantity} {shelfLife.duration.unit_id}{shelfLife.storage_condition?` · ${shelfLife.storage_condition}`:""}

}{JSON.parse(additional.notes_json??"[]").length>0&&
    {JSON.parse(additional.notes_json).map((note:string)=>
  • {note}
  • )}
}
} +
+ {!editing&&} + {editing&&} +
diff --git a/src/application/pages/app/recipes/index.astro b/src/application/pages/app/recipes/index.astro new file mode 100644 index 0000000..4206801 --- /dev/null +++ b/src/application/pages/app/recipes/index.astro @@ -0,0 +1,4 @@ +--- +export const prerender=false; +return Astro.redirect("/app/?type=recipe",302); +--- diff --git a/src/application/pages/app/recipes/new.astro b/src/application/pages/app/recipes/new.astro new file mode 100644 index 0000000..52fa5a0 --- /dev/null +++ b/src/application/pages/app/recipes/new.astro @@ -0,0 +1,12 @@ +--- +export const prerender=false; +import BaseLayout from "../../../../layouts/BaseLayout.astro"; +import { openDatabase,refreshSiteProjection } from "../../../../lib/database"; +const database=openDatabase({readOnly:false}); +if(!database)return Astro.redirect("/app/?error=database-missing",303); +let error:string|undefined; +const units=database.prepare("SELECT id,name,symbol FROM units ORDER BY dimension,name").all() as Array<{id:string;name:string;symbol:string}>; +if(Astro.request.method==="POST"){try{const form=await Astro.request.formData();const title=String(form.get("title")??"").trim();const yieldQuantity=Number(form.get("yield_quantity"));const yieldUnitId=String(form.get("yield_unit_id")??"");if(!title)throw new Error("Title is required.");if(!Number.isFinite(yieldQuantity)||yieldQuantity<=0)throw new Error("Yield must be greater than zero.");if(!database.prepare("SELECT 1 FROM units WHERE id=?").get(yieldUnitId))throw new Error("Unknown yield unit.");const base=title.toLocaleLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")||"recipe";let id=base,suffix=2;while(database.prepare("SELECT 1 FROM recipes WHERE id=?").get(id))id=`${base}_${suffix++}`;database.exec("BEGIN IMMEDIATE");try{database.prepare(`INSERT INTO recipes(id,schema_version,revision,status,title,summary,categories_json,tags_json,yield_quantity,yield_unit_id,yield_servings,yield_basis,scaling_mode,scaling_basis_id,scaling_basis_quantity,scaling_basis_unit_id,notes_json,source_json) VALUES (?,1,1,'draft',?,NULL,'[]','[]',?,?,NULL,NULL,'linear',NULL,NULL,NULL,'[]','{}')`).run(id,title,yieldQuantity,yieldUnitId);database.prepare("INSERT INTO recipe_components(recipe_id,id,position,name,notes_json) VALUES (?,'main',1,'Main','[]')").run(id);database.prepare("INSERT INTO recipe_steps(recipe_id,id,position,instruction,critical_control_point) VALUES (?,'step_1',1,'TODO: Add preparation instructions.',0)").run(id);database.exec("COMMIT");}catch(cause){database.exec("ROLLBACK");throw cause;}refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1`,303);}catch(cause){error=cause instanceof Error?cause.message:"Unable to create recipe.";}} +database.close(); +--- +

Recipes

New recipe

Create the recipe, then add its ingredients and preparation.

Recipe details{error&&
{error}
}
Cancel
diff --git a/src/application/pages/tools/purchasing-review.astro b/src/application/pages/tools/purchasing-review.astro new file mode 100644 index 0000000..dbc70c3 --- /dev/null +++ b/src/application/pages/tools/purchasing-review.astro @@ -0,0 +1,9 @@ +--- +export const prerender = true; +import fs from "node:fs"; import path from "node:path"; import YAML from "yaml"; +import BaseLayout from "../../../layouts/BaseLayout.astro"; import PurchasingReview from "../../../components/PurchasingReview"; +import { ingredients } from "../../../lib/data"; +const file=path.resolve(process.cwd(),"generated/receipt-product-candidates.yaml"); const data=fs.existsSync(file)?YAML.parse(fs.readFileSync(file,"utf8")):null; +const ingredientOptions=[...ingredients.values()].map(({id,name})=>({id,name})).sort((a,b)=>a.name.localeCompare(b.name)); +--- +

Local data tool

Receipt product review

Link actual Walmart and Sam's Club products to canonical ingredients.

{data?:
Run scripts/receipt-products propose, then rebuild.
}
diff --git a/src/components/DetailUtility.astro b/src/components/DetailUtility.astro new file mode 100644 index 0000000..7c1ec3e --- /dev/null +++ b/src/components/DetailUtility.astro @@ -0,0 +1,27 @@ +--- +interface Props { section?: string; sectionHref?: string } +const { section, sectionHref } = Astro.props; +const inferred = Astro.url.pathname.includes("/ingredients/") + ? { label:"Ingredients", href:"/app/?type=ingredient" } + : Astro.url.pathname.includes("/recipe-books/") + ? { label:"Recipe Books", href:"/app/?type=book" } + : Astro.url.pathname.includes("/recipes/") + ? { label:"Recipes", href:"/app/?type=recipe" } + : { label:undefined, href:"/app/" }; +const resolvedSection=section??inferred.label; +const resolvedHref=sectionHref??inferred.href; +--- + diff --git a/src/components/EntityDirectory.tsx b/src/components/EntityDirectory.tsx new file mode 100644 index 0000000..c0acaf7 --- /dev/null +++ b/src/components/EntityDirectory.tsx @@ -0,0 +1,45 @@ +import { useRef,useState } from "preact/hooks"; + +export type DirectoryRow = { + id:string; name:string; href?:string; kind:"recipe"|"ingredient"|"book"|"purchase"; icon:string; +}; +type Props={ rows:DirectoryRow[]; entityType:DirectoryRow["kind"]; emptyMessage:string }; + +export default function EntityDirectory({rows,entityType,emptyMessage}:Props) { + const [selected,setSelected]=useState([]),[deleting,setDeleting]=useState(false),[error,setError]=useState(""); + const [pendingDelete,setPendingDelete]=useState([]); + const dialog=useRef(null); + const allSelected=rows.length>0&&selected.length===rows.length; + const toggle=(id:string)=>setSelected(current=>current.includes(id)?current.filter(value=>value!==id):[...current,id]); + const requestDelete=(ids:string[])=>{if(!ids.length)return;setPendingDelete(ids);dialog.current?.showModal();}; + const remove=async()=>{ + const ids=pendingDelete; + if(!ids.length)return; + setDeleting(true);setError(""); + const response=await fetch("/api/app/entities/delete",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:entityType,ids})}); + const result=await response.json(); + if(!response.ok){setError(result.error??"Unable to delete selection.");setDeleting(false);dialog.current?.close();return;} + location.reload(); + }; + return
+
+ {if(input)input.indeterminate=selected.length>0&&!allSelected;}} onChange={()=>setSelected(allSelected?[]:rows.map(row=>row.id))}/> + {selected.length?`${selected.length} selected`:""} + {selected.length>0&&<>} +
+ {error&&

{error}

} +
{rows.map(row=>
+ toggle(row.id)}/> + {row.icon} + {row.href?{row.name}:{row.name}} +
+
)}
+ {rows.length===0&&
{emptyMessage}
} + {if(!deleting)setPendingDelete([]);}}> +
+

Delete {pendingDelete.length===1?"item":`${pendingDelete.length} items`}?

+

This permanently removes the selected {pendingDelete.length===1?entityType:`${entityType} items`}. This action cannot be undone.

+
+
+
; +} diff --git a/src/components/NutritionPanel.test.ts b/src/components/NutritionPanel.test.ts new file mode 100644 index 0000000..e3352d8 --- /dev/null +++ b/src/components/NutritionPanel.test.ts @@ -0,0 +1,10 @@ +import { describe,expect,it } from "vitest"; +import { labelCalories } from "./NutritionPanel"; + +describe("nutrition label display rounding",()=>{ + it("uses FDA calorie increments",()=>{ + expect(labelCalories(4.9)).toBe(0); + expect(labelCalories(47)).toBe(45); + expect(labelCalories(96)).toBe(100); + }); +}); diff --git a/src/components/NutritionPanel.tsx b/src/components/NutritionPanel.tsx new file mode 100644 index 0000000..576b3b0 --- /dev/null +++ b/src/components/NutritionPanel.tsx @@ -0,0 +1,40 @@ +import type { NutritionResult } from "../lib/nutrition"; + +const dailyValues: Record = { total_fat_g: 78, saturated_fat_g: 20, cholesterol_mg: 300, sodium_mg: 2300, carbohydrate_g: 275, dietary_fiber_g: 28, vitamin_d_mcg: 20, calcium_mg: 1300, iron_mg: 18, potassium_mg: 4700 }; +const rows = [["Total Fat", "total_fat_g", "g"], ["Saturated Fat", "saturated_fat_g", "g"], ["Cholesterol", "cholesterol_mg", "mg"], ["Sodium", "sodium_mg", "mg"], ["Total Carbohydrate", "carbohydrate_g", "g"], ["Dietary Fiber", "dietary_fiber_g", "g"], ["Total Sugars", "total_sugars_g", "g"], ["Protein", "protein_g", "g"]] as const; + +export type NutritionIngredientStatus = { id:string; name:string; href:string; weightG?:number; mapped:boolean; source?:string; kind?:"ingredient"|"recipe" }; + +const nearest=(value:number,increment:number)=>Math.round(value/increment)*increment; +export const labelCalories=(value:number)=>value<5?0:nearest(value,value<=50?5:10); +const labelAmount=(key:string,value:number,unit:string)=>{ + if(key==="cholesterol_mg") return value<2?"0mg":value<=5?"<5mg":`${nearest(value,5)}mg`; + if(key==="sodium_mg") return `${value<5?0:nearest(value,value<=140?5:10)}mg`; + if(["total_fat_g","saturated_fat_g","trans_fat_g"].includes(key)) return `${value<.5?0:value<5?nearest(value,.5):nearest(value,1)}g`; + if(unit==="g") return value<.5?"0g":value<1?"<1g":`${nearest(value,1)}g`; + return `${Math.round(value)}${unit}`; +}; + +export default function NutritionPanel({ nutrition, servings, factor, ingredients=[], editable=false, revision }: { nutrition: NutritionResult; servings?: number; factor: number; ingredients?:NutritionIngredientStatus[]; editable?:boolean; revision?:number }) { + const facts = nutrition.perServing ?? nutrition.per100g; + if (!facts) return null; + const servingWeight = servings && nutrition.yieldWeightG ? nutrition.yieldWeightG / servings : 100; + const scaledServings = servings ? servings * factor : undefined; + const amount = (key: string, unit: string) => labelAmount(key,facts[key]??0,unit); + const dv = (key: string) => dailyValues[key] ? Math.round(((facts[key] ?? 0) / dailyValues[key]) * 100) : undefined; + const ready=Boolean(servings)&&nutrition.completeness>=.999; + return
+
+

Nutrition label

{ready?"Ready to print":"Complete the items below to generate a final label."}

+
{servings?"✓":"!"}
Serving size{servings?`${Math.round(servings*factor*100)/100} servings per scaled recipe · ${Math.round(servingWeight)} g each`:editable?"Enter the number of servings this recipe yields.":"Add servings in edit mode."}{editable&&
}
+ {ingredients.length>0&&
Ingredient nutritional data{ingredients.filter(item=>item.mapped).length} of {ingredients.length} connected
{[...ingredients].sort((a,b)=>(b.weightG??-1)-(a.weightG??-1)).map(item=>{item.mapped?"✓":"!"}{item.name}{item.mapped?(item.source??(item.kind==="recipe"?"Calculated from sub-recipe":"USDA connected")):"Add nutritional data"}{item.weightG!=null&&{Math.round(item.weightG*100)/100} g})}
} +
+
+

Nutrition Facts

{scaledServings &&

{Math.round(scaledServings * 100) / 100} servings per scaled recipe

}
Serving size{nutrition.perServing ? `1 serving (${Math.round(servingWeight)} g)` : "100 g"}
+

Amount per serving

Calories{labelCalories(facts.energy_kcal ?? 0)}

% Daily Value*

+
{rows.filter(([, key]) => facts[key] != null).map(([label, key, unit]) =>
{label} {amount(key, unit)}
{dv(key) != null &&
{dv(key)}%
}
)}
+

* The % Daily Value tells you how much a nutrient in a serving contributes to a daily diet. A 2,000 calorie diet is used for general nutrition advice.

+
+

{ready?"Calculated label":"Draft calculation"} · {Math.round(nutrition.completeness * 100)}% mapped. Scaled batch: {Math.round((nutrition.batch.energy_kcal ?? 0) * factor)} kcal. Nutrition and allergen analysis must be professionally verified before regulatory use.

+
; +} diff --git a/src/components/PurchaseItemForm.astro b/src/components/PurchaseItemForm.astro new file mode 100644 index 0000000..c016796 --- /dev/null +++ b/src/components/PurchaseItemForm.astro @@ -0,0 +1,33 @@ +--- +type Unit = { id: string; name: string; symbol: string; dimension: string }; +type PurchaseItem = { + id: string; name: string; brand: string | null; supplier_id: string | null; supplier_sku: string | null; + status: string; package_quantity: number; package_unit_id: string; units_per_case: number; usable_yield_factor: number; + latest_price: number | null; latest_currency: string | null; latest_date: string | null; + prices: Array<{ effective_at: string; currency: string; amount: number }>; +}; +interface Props { item?: PurchaseItem; units: Unit[] } +const { item, units } = Astro.props; +const today = new Date().toISOString().slice(0, 10); +const usableUnits = item ? item.package_quantity * item.units_per_case * item.usable_yield_factor : undefined; +const unitCost = item?.latest_price != null && usableUnits ? item.latest_price / usableUnits : undefined; +const unit = item ? units.find((candidate) => candidate.id === item.package_unit_id) : undefined; +--- +
+ + + + + + + + + + + + + + {unitCost!=null&&

Current usable cost{item?.latest_currency} {unitCost.toFixed(unitCost<0.1?3:2)} / {unit?.symbol??item?.package_unit_id}

} +
+ {item?.prices.length&&
Price history ({item.prices.length}){item.prices.map((price)=>)}
{price.effective_at}{price.currency} {price.amount.toFixed(2)}
} +
diff --git a/src/components/PurchasingReview.tsx b/src/components/PurchasingReview.tsx new file mode 100644 index 0000000..f656b52 --- /dev/null +++ b/src/components/PurchasingReview.tsx @@ -0,0 +1,15 @@ +import { useEffect, useMemo, useState } from "preact/hooks"; +type Candidate={ingredient_id:string;name:string;score:number}; +type Product={supplier_id:string;supplier_sku:string;name:string;url?:string;package?:{quantity:number;unit_id:string};prices:Array<{amount:number;effective_at:string}>;ingredient_candidates:Candidate[]}; +type Props={products:Product[];ingredients:Array<{id:string;name:string}>}; type Decisions=Record; +const STORAGE_KEY="recipe-book-purchasing-decisions-v1"; +export default function PurchasingReview({products,ingredients}:Props){ + const [decisions,setDecisions]=useState({}); const [query,setQuery]=useState(""); const [unresolved,setUnresolved]=useState(true); + useEffect(()=>{try{setDecisions(JSON.parse(localStorage.getItem(STORAGE_KEY)??"{}"))}catch{}},[]); + const choose=(key:string,value:string|null)=>{const next={...decisions,[key]:value};setDecisions(next);localStorage.setItem(STORAGE_KEY,JSON.stringify(next))}; + const visible=useMemo(()=>products.filter(p=>{const key=`${p.supplier_id}:${p.supplier_sku}`;return p.name.toLowerCase().includes(query.toLowerCase())&&(!unresolved||!(key in decisions))}),[products,query,unresolved,decisions]); + const download=()=>{const url=URL.createObjectURL(new Blob([JSON.stringify({schema_version:1,generated_at:new Date().toISOString(),decisions},null,2)],{type:"application/json"}));const anchor=document.createElement("a");anchor.href=url;anchor.download="purchasing-decisions.json";anchor.click();URL.revokeObjectURL(url)}; + return
{Object.keys(decisions).length} / {products.length} reviewedProducts without explicit package sizes cannot be imported yet
setQuery(e.currentTarget.value)}/>
+ {visible.map(product=>{const key=`${product.supplier_id}:${product.supplier_sku}`;return
{product.name}

{product.supplier_id.replace("_"," ")} · SKU {product.supplier_sku} · {product.package?`${product.package.quantity} ${product.package.unit_id}`:"package unknown"} · latest ${product.prices.at(-1)?.amount.toFixed(2)}

{product.ingredient_candidates.map(candidate=>)}{product.url&&

Inspect product ↗

}
})} +
; +} diff --git a/src/components/RecipeCalculator.tsx b/src/components/RecipeCalculator.tsx new file mode 100644 index 0000000..2a09602 --- /dev/null +++ b/src/components/RecipeCalculator.tsx @@ -0,0 +1,180 @@ +import { useEffect, useMemo, useState } from "preact/hooks"; +import type { CalculatorComponent, CalculatorItem, Unit } from "../lib/types"; +import { convert } from "../lib/measurement"; +import type { NutritionResult } from "../lib/nutrition"; +import type { CostResult } from "../lib/costing"; +import NutritionPanel from "./NutritionPanel"; +import { number, roundForDisplay } from "../lib/format"; + +type Props = { + components: CalculatorComponent[]; + units: Record; + basisUnitId: string; + yieldQuantity: number; + yieldUnitId: string; + mode: "amount" | "percentage" | "hybrid"; + nutrition: NutritionResult; + cost: CostResult; + servings?: number; + showDerived?: boolean; + yieldConversions?: CalculatorItem["measureConversions"]; +}; + +function itemUnits(item: CalculatorItem, units: Record) { + const dimensions = new Set([units[item.amount.unit_id]?.dimension]); + for (const conversion of item.measureConversions ?? []) { + dimensions.add(units[conversion.from.unit_id]?.dimension); + dimensions.add(units[conversion.to.unit_id]?.dimension); + } + return Object.values(units).filter((unit) => dimensions.has(unit.dimension)); +} + +function convertItem(quantity: number, fromUnitId: string, toUnitId: string, item: CalculatorItem, units: Record) { + if (units[fromUnitId]?.dimension === units[toUnitId]?.dimension) return convert(quantity, fromUnitId, toUnitId, units); + for (const equivalency of item.measureConversions ?? []) { + const fromDimension = units[equivalency.from.unit_id]?.dimension; + const toDimension = units[equivalency.to.unit_id]?.dimension; + if (units[fromUnitId]?.dimension === fromDimension && units[toUnitId]?.dimension === toDimension) { + const atBridge = convert(quantity, fromUnitId, equivalency.from.unit_id, units); + return convert(atBridge * equivalency.to.quantity / equivalency.from.quantity, equivalency.to.unit_id, toUnitId, units); + } + if (units[fromUnitId]?.dimension === toDimension && units[toUnitId]?.dimension === fromDimension) { + const atBridge = convert(quantity, fromUnitId, equivalency.to.unit_id, units); + return convert(atBridge * equivalency.from.quantity / equivalency.to.quantity, equivalency.from.unit_id, toUnitId, units); + } + } + throw new Error(`No reviewed equivalency from ${fromUnitId} to ${toUnitId}`); +} + +export default function RecipeCalculator({ components, units, basisUnitId, yieldQuantity, yieldUnitId, nutrition, cost, servings, showDerived = true, yieldConversions = [] }: Props) { + const [factor, setFactor] = useState(1); + const [calculatePercent,setCalculatePercent]=useState(true); + const [percentMode,setPercentMode]=useState<"standard"|"bakers">("standard"); + const [yieldDisplayUnitId, setYieldDisplayUnitId] = useState(yieldUnitId); + const [lineUnits, setLineUnits] = useState>({}); + const validFactor = Number.isFinite(factor) && factor >= 0 ? factor : 0; + useEffect(() => { window.dispatchEvent(new CustomEvent("recipe-scale-change", { detail:validFactor })); }, [validFactor]); + const itemWeight=(item:CalculatorItem)=>{try{return convertItem(item.amount.quantity,item.amount.unit_id,"gram",item,units);}catch{return undefined;}}; + const total = useMemo( + () => components.flatMap((component) => component.items).reduce((sum, item) => { + try { return sum + convertItem(item.amount.quantity * validFactor, item.amount.unit_id, basisUnitId, item, units); } + catch { return sum; } + }, 0), + [components, validFactor, basisUnitId, units], + ); + const unconvertedCount=useMemo(()=>components.flatMap((component)=>component.items).filter((item)=>{try{convertItem(item.amount.quantity,item.amount.unit_id,basisUnitId,item,units);return false;}catch{return true;}}).length,[components,basisUnitId,units]); + const percentageBase=components.flatMap(component=>component.items).filter(item=>percentMode==="standard"||item.basisMember).reduce((sum,item)=>sum+(itemWeight(item)??0),0); + const baseItems=components.flatMap(component=>component.items).filter(item=>item.basisMember); + const basisUnit = units[basisUnitId]; + const yieldItem = { id:"yield", label:"Yield", amount:{quantity:yieldQuantity,unit_id:yieldUnitId}, measureConversions:yieldConversions } as CalculatorItem; + const yieldUnits = itemUnits(yieldItem,units); + const scaledYield = convertItem(yieldQuantity * validFactor,yieldUnitId,yieldDisplayUnitId,yieldItem,units); + const changeYield = (value: number) => { + const canonicalQuantity = convertItem(value,yieldDisplayUnitId,yieldUnitId,yieldItem,units); + setFactor(yieldQuantity > 0 ? canonicalQuantity / yieldQuantity : 1); + }; + + return ( +
+
+
+

Scalable formula

+

Ingredients

+
+ + +
{calculatePercent&&}
+
+

1× produces {number(yieldQuantity)} {units[yieldUnitId]?.symbol??yieldUnitId} finished yield. Changing the multiplier, finished yield, or any ingredient amount scales the entire recipe.

+ + {calculatePercent&&percentMode==="bakers"&&baseItems.length>0&&
Base
{baseItems.map(item=>{const displayUnitId=lineUnits[item.id]??item.amount.unit_id;const displayQuantity=convertItem(item.amount.quantity*validFactor,item.amount.unit_id,displayUnitId,item,units);return

{const canonicalQuantity=convertItem(Number(event.currentTarget.value),displayUnitId,item.amount.unit_id,item,units);setFactor(item.amount.quantity>0?canonicalQuantity/item.amount.quantity:1)}}/>{item.label}

})}
} + {components.map((component) => ( +
+ {components.length > 1 &&

{component.name}

} +
+ + {calculatePercent&&} + + {component.items.filter(item=>percentMode!=="bakers"||!calculatePercent||!item.basisMember).map((item) => { + const displayUnitId = lineUnits[item.id] ?? item.amount.unit_id; + const compatibleUnits = itemUnits(item, units); + const displayQuantity = convertItem(item.amount.quantity * validFactor, item.amount.unit_id, displayUnitId, item, units); + const changeLineQuantity = (value: number) => { + const canonicalQuantity = convertItem(value, displayUnitId, item.amount.unit_id, item, units); + setFactor(item.amount.quantity > 0 ? canonicalQuantity / item.amount.quantity : 1); + }; + return ( + + + {calculatePercent&&} + + + ); + })} + +
Ingredient{percentMode==="standard"?"Standard %":"Baker's %"}Weight
+ {item.href ? {item.label} : item.label} + {item.optional && optional} + {item.notes && {item.notes}} + {itemWeight(item)==null||percentageBase<=0?"—":`${number(itemWeight(item)!/percentageBase*100)}%`} changeLineQuantity(Number(event.currentTarget.value))}/>
+
+
+ ))} +
Scaled ingredient total{number(total)} {basisUnit?.symbol ?? basisUnitId}
+ {unconvertedCount>0&&

{unconvertedCount} ingredient {unconvertedCount===1?"amount is":"amounts are"} excluded from this total because no weight or volume equivalency is available.

} + {showDerived && } +
+ ); +} + +export function DerivedValues({ nutrition, cost, servings, factor }: { nutrition: NutritionResult; cost: CostResult; servings?: number; factor: number }) { + const money = new Intl.NumberFormat("en-US", { style: "currency", currency: cost.currency, minimumFractionDigits: 2, maximumFractionDigits: 4 }); + return
+
+
+

Derived estimate

Recipe cost

{Math.round(cost.completeness * 100)}% priced
+ {cost.batch != null ?
+
Scaled batch
{money.format(cost.batch * factor)}
+ {cost.perServing != null &&
Per serving
{money.format(cost.perServing)}
} + {cost.per100g != null &&
Per 100 g
{money.format(cost.per100g)}
} +
:

No usable purchase prices are available yet.

} + {cost.completeness < 1 &&

Partial estimate; unpriced ingredients are excluded.

} +
+
; +} + +export function LiveDerivedValues({ nutrition, cost, servings }: { nutrition: NutritionResult; cost: CostResult; servings?: number }) { + const [factor,setFactor]=useState(1); + useEffect(()=>{const update=(event:Event)=>setFactor((event as CustomEvent).detail);window.addEventListener("recipe-scale-change",update);return()=>window.removeEventListener("recipe-scale-change",update);},[]); + return ; +} + +function useLiveFactor() { + const [factor,setFactor]=useState(1); + useEffect(()=>{const update=(event:Event)=>setFactor((event as CustomEvent).detail);window.addEventListener("recipe-scale-change",update);return()=>window.removeEventListener("recipe-scale-change",update);},[]); + return factor; +} + +export function LiveCostValues({ cost }: { cost: CostResult }) { + const factor=useLiveFactor(); + const money=new Intl.NumberFormat("en-US",{style:"currency",currency:cost.currency,minimumFractionDigits:2,maximumFractionDigits:4}); + return

Recipe Cost

{Math.round(cost.completeness*100)}% priced
{cost.batch!=null?
Scaled batch
{money.format(cost.batch*factor)}
{cost.perServing!=null&&
Per serving
{money.format(cost.perServing*factor)}
}{cost.per100g!=null&&
Per 100 g
{money.format(cost.per100g)}
}
:

No usable purchase prices are available yet.

}{cost.completeness<1&&

Partial estimate; unpriced ingredients are excluded.

}{cost.warnings.length>0&&
{cost.warnings.length} costing {cost.warnings.length===1?"issue":"issues"}
    {cost.warnings.map(warning=>
  • {warning}
  • )}
}
; +} + +export function LiveNutritionValues({ nutrition,servings,ingredients=[],editable=false,revision }: { nutrition:NutritionResult; servings?:number; ingredients?:import("./NutritionPanel").NutritionIngredientStatus[]; editable?:boolean; revision?:number }) { + return ; +} diff --git a/src/components/RecipeCard.astro b/src/components/RecipeCard.astro new file mode 100644 index 0000000..0e15dc1 --- /dev/null +++ b/src/components/RecipeCard.astro @@ -0,0 +1,12 @@ +--- +import type { Recipe } from "../lib/types"; +import { recipeHref, titleCase } from "../lib/data"; +interface Props { recipe: Recipe } +const { recipe } = Astro.props; +--- +
+
{titleCase(recipe.categories[0] ?? "recipe")}{recipe.status}
+

{recipe.title}

+

{recipe.summary ?? `${recipe.components.length} component${recipe.components.length === 1 ? "" : "s"} · ${recipe.steps.length} preparation step${recipe.steps.length === 1 ? "" : "s"}`}

+
{recipe.tags.slice(0, 4).map((tag) => #{tag})}
+
diff --git a/src/components/RecipeList.astro b/src/components/RecipeList.astro new file mode 100644 index 0000000..1d70412 --- /dev/null +++ b/src/components/RecipeList.astro @@ -0,0 +1,8 @@ +--- +import RecipeCard from "./RecipeCard.astro"; +import type { Recipe } from "../lib/types"; +interface Props { recipes: Recipe[]; heading?: string } +const { recipes, heading } = Astro.props; +--- +{heading &&

{heading}

} +
{recipes.map((recipe) => )}
diff --git a/src/components/RecipeStructureEditor.tsx b/src/components/RecipeStructureEditor.tsx new file mode 100644 index 0000000..f816a5f --- /dev/null +++ b/src/components/RecipeStructureEditor.tsx @@ -0,0 +1,629 @@ +import { useEffect, useState } from "preact/hooks"; +import type { RecipeStructure } from "../lib/database"; +import { percentage, targetWeight } from "../lib/percentages"; + +type Option = { id: string; name: string }; +type Props = { + recipeId: string; + initial: RecipeStructure; + ingredients: Option[]; + recipes: Option[]; + units: Array