@crvouga/mockingbird-service-edamam 3.7.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Changelog — @crvouga/mockingbird-service-edamam
2
2
 
3
- ## 3.7.0 (2026-10-19)
3
+ ## 3.9.0 (2026-10-21)
4
+
5
+ ### Features
6
+
7
+ - add manual response controls ([4599960](https://github.com/crvouga/mockingbird/commit/45999603e8b860c633181367afc7baa906ba486b))
8
+
9
+ ## 3.8.0 (2026-10-20)
10
+
11
+ ### Features
12
+
13
+ - raise the serve and fleet body limit to the S3 maximum ([86b9e2b](https://github.com/crvouga/mockingbird/commit/86b9e2b80bcaaaef57f52edbac50b27da0b42f33))
14
+ - validate block limits, filter nutrients, list block children ([2acb823](https://github.com/crvouga/mockingbird/commit/2acb823ba66b30f3d03221996e015c127b0f72c6))
15
+
16
+ ## 3.7.0 (2026-10-18)
4
17
 
5
18
  ### Features
6
19
 
package/README.md CHANGED
@@ -64,7 +64,7 @@ also accept `Authorization: Basic app_id:app_key`, which our adapter sends).
64
64
 
65
65
  | Route | Behaviour |
66
66
  | --- | --- |
67
- | `GET /api/food-database/v2/parser` | `ingr` is parsed into a leading quantity ("2", "1/2", "a", "two"), a measure the food has ("cup", "large", "slice", "g", "oz") and the best-matching food → `parsed[]`; every food sharing a word → `hints[]` with `measures`. Filters: `categoryLabel` (`food` drops meals), `category`, `health` (repeatable), `calories` (per 100 g). `upc` looks up a packaged food (unknown UPC 404). |
67
+ | `GET /api/food-database/v2/parser` | `ingr` is parsed into a leading quantity ("2", "1/2", "a", "two"), a measure the food has ("cup", "large", "slice", "g", "oz") and the best-matching food → `parsed[]`; every food sharing a word → `hints[]` with `measures`. Filters: `categoryLabel` (`food` drops meals), `category`, `health` (repeatable), `calories` (per 100 g), `nutrients[CODE]` (per 100 g, see below). `upc` looks up a packaged food (unknown UPC 404). |
68
68
  | `POST /api/food-database/v2/nutrients` | `{ingredients: [{quantity, measureURI, foodId}]}` → `calories`, `totalWeight`, `totalNutrients`, `totalDaily`, `dietLabels`, `healthLabels`, `ingredients[].parsed[]`; an unknown food or measure is 422. |
69
69
  | `POST /api/food-database/nutrients-from-image?beta=true` | `{image: data URL or http URL}` → `{parsed: {food, quantity, measure}, recipe: {label, calories, totalNutrients}}`, deterministic per image (or pinned with `PUT /__admin/vision`). |
70
70
  | `GET /api/nutrition-data?ingr=` | One ingredient line; unparsable is 422. |
@@ -108,6 +108,18 @@ and the Python client, which concatenate paths; the meal adapter resolves paths
108
108
 
109
109
  - Edamam's NLP and databases: the parser understands leading quantities, known measures and
110
110
  corpus food names only; real food and recipe content needs a recorded corpus.
111
+ - Parser `nutrients[CODE]` is a **best guess, not oracle-verified** (vendor docs only say the
112
+ Food Database can "search for food by given nutrient quantity"; the query syntax, the error for a
113
+ malformed range and any plan restriction were never observed live). The emulator reads
114
+ `nutrients[PROCNT]=20+`, `=5` (at most) and `=5-15` (inclusive) like `calories`, against the
115
+ food's per-100 g `nutrients`, and a raw `+` that decoded to a space still means "or more".
116
+ Several codes, a repeated code and `health` / `calories` / `category` / `categoryLabel` all must
117
+ hold; nothing matching is `200` with `hints: []` and `parsed: []`. A food with no value for the
118
+ code never matches. Any code shaped like a nutrient code is accepted, but the built-in corpus
119
+ carries only `ENERC_KCAL`, `PROCNT`, `FAT`, `CHOCDF`, `FIBTG` and `SUGAR`, so codes such as `NA` or
120
+ `FE` match only foods seeded with `POST /__admin/foods` that carry them (an emulator limitation,
121
+ not a vendor answer). A malformed range or code is `400 bad_request`. The `upc` lookup ignores the
122
+ filters, as it does for `calories`.
111
123
  - Food Database autocomplete, brand search and `nutrients` qualifiers; Recipe Search user
112
124
  recipes (`type=user`), `field=` projection and images other than the URL.
113
125
  - Meal Planner plan-level `fit` beyond a day-calorie check, `mark` weighting, nested
@@ -9,7 +9,7 @@ import {
9
9
  parseFaultHeader,
10
10
  resolveAdminPrefix,
11
11
  restoreClock
12
- } from "./chunk-ULEKWBW5.js";
12
+ } from "./chunk-EWIGLQLG.js";
13
13
 
14
14
  // ../../adapters/node/dist/cli.js
15
15
  import { readFile as readFile5 } from "node:fs/promises";
@@ -3057,7 +3057,7 @@ async function preflightFleet(config, options) {
3057
3057
  break;
3058
3058
  }
3059
3059
  }
3060
- targets.set(name, { ...target, packageVersion: packageVersion ?? "3.7.0" });
3060
+ targets.set(name, { ...target, packageVersion: packageVersion ?? "3.9.0" });
3061
3061
  } catch (error) {
3062
3062
  throw new Error(`service ${name}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
3063
3063
  }
@@ -3283,7 +3283,11 @@ var serve = async (api, options = {}) => {
3283
3283
  // ../../adapters/node/dist/listen.js
3284
3284
  var listen = async (api, options = {}) => {
3285
3285
  const host = options.host ?? "127.0.0.1";
3286
- const server = await serve(api, { port: options.port ?? 0, host });
3286
+ const server = await serve(api, {
3287
+ port: options.port ?? 0,
3288
+ host,
3289
+ ...options.maxBodyBytes !== void 0 ? { maxBodyBytes: options.maxBodyBytes } : {}
3290
+ });
3287
3291
  const address = server.address();
3288
3292
  const port = typeof address === "object" && address !== null ? address.port : options.port ?? 0;
3289
3293
  const shown = host.includes(":") ? `[${host}]` : host;
@@ -3482,7 +3486,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3482
3486
  try {
3483
3487
  server = await listen(api, {
3484
3488
  port: entry.port ?? target.defaultPort,
3485
- host: entry.host ?? "127.0.0.1"
3489
+ host: entry.host ?? "127.0.0.1",
3490
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
3486
3491
  });
3487
3492
  target.listening?.(server);
3488
3493
  } catch (error) {
@@ -4873,7 +4878,11 @@ var start = async (target, values, config) => {
4873
4878
  });
4874
4879
  if (config.idBase !== void 0)
4875
4880
  runtime.setIdBase?.(config.idBase);
4876
- const listening = await listen(runtime, { port: config.port, host: config.host });
4881
+ const listening = await listen(runtime, {
4882
+ port: config.port,
4883
+ host: config.host,
4884
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
4885
+ });
4877
4886
  target.listening?.(listening);
4878
4887
  console.log(`${target.name} emulator listening on ${listening.url}`);
4879
4888
  console.log(`${target.name} health: GET ${listening.url}${adminPrefix}/health`);
@@ -5028,4 +5037,4 @@ export {
5028
5037
  createServer2 as createServer,
5029
5038
  serveTarget
5030
5039
  };
5031
- //# sourceMappingURL=chunk-HJNYL3OH.js.map
5040
+ //# sourceMappingURL=chunk-5QWKKFKS.js.map