@chronicle.app/foodnoms 0.3.0 → 0.4.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @chronicle.app/foodnoms
2
2
 
3
- Read the FoodNoms app's SQLite database with `FoodNomsExtractor`, then emit one `EatAction` or `DrankAction` per logged food entry with `FoodNomsTransformer`. `input` defaults to `~/Library/Containers/com.algebraiclabs.foodnoms/Data/Documents/db.db`; reading it needs Full Disk Access. The connection is read-only via built-in `node:sqlite`.
3
+ Read the FoodNoms app's SQLite database with `FoodNomsExtractor`, then emit one `EatAction` or `DrinkAction` per logged food entry with `FoodNomsTransformer`. `input` defaults to `~/Library/Containers/com.algebraiclabs.foodnoms/Data/Documents/db.db`; reading it needs Full Disk Access. The connection is read-only via built-in `node:sqlite`.
4
4
 
5
5
  ```sh
6
6
  chronicle extract foodnoms --limit 0
@@ -8,7 +8,7 @@ chronicle extract foodnoms --limit 0
8
8
 
9
9
  Records are food entries, newest first, joined to their meal slot. `since`/`until` are inclusive bounds on the entry date, and `limit: 0` means unlimited. FoodNoms stores dates as UTC text; the extractor adds a `Z` and turns the entry's blob ID into a dashed UUID.
10
10
 
11
- Each action happens at the entry's `timestamp` and is keyed by the entry's ID without its type. FoodNoms has no food-or-drink flag, so an entry whose name contains a common drink word becomes a `DrankAction`, and anything else an `EatAction`. Keeping the type out of the key lets that guess change without changing the action's identity.
11
+ Each action happens at the entry's `timestamp` and is keyed by the entry's ID without its type. FoodNoms has no food-or-drink flag, so an entry whose name contains a common drink word becomes a `DrinkAction`, and anything else an `EatAction`. Keeping the type out of the key lets that guess change without changing the action's identity.
12
12
 
13
13
  The object is a `Meal` keyed by the same entry ID and named after the food. Its `category` is the meal slot: the built-in slots map to Breakfast, Lunch, Dinner and Snacks, a customized slot uses its own name, and an unnamed custom slot has none. The `description` joins the slot, brand, amount and calories.
14
14
 
@@ -102,7 +102,13 @@ export class FoodNomsExtractor extends SqliteExtractor {
102
102
  m.name as mealTypeName,
103
103
  m.timeRangeStart as mealTimeRangeStart,
104
104
  m.timeRangeEnd as mealTimeRangeEnd,
105
- m.sortIndex as mealSortIndex
105
+ -- FoodNoms can store sortIndex near Int64.min (e.g. -9223372036854775805),
106
+ -- which node:sqlite refuses to read as a number, so out-of-range values
107
+ -- come through as text.
108
+ CASE
109
+ WHEN m.sortIndex BETWEEN -9007199254740991 AND 9007199254740991 THEN m.sortIndex
110
+ ELSE CAST(m.sortIndex AS TEXT)
111
+ END as mealSortIndex
106
112
  FROM foodEntryRecord f
107
113
  LEFT JOIN mealTypeRecord m ON f.mealTypeID = m.mealTypeID
108
114
  WHERE ${conditions.join(' AND ')}
@@ -77,7 +77,7 @@ export default class FoodNomsTransformer extends ChronicleTransformer {
77
77
  // action. This also keeps FoodNoms consumptions shaped like the historical
78
78
  // `ate X` / `drank X` log so the two can sit on one timeline.
79
79
  const shared = {
80
- timestamp: record.data.date,
80
+ timestamp: new Date(record.data.date),
81
81
  '@key': ['source', 'sourceId'],
82
82
  source: 'foodnoms',
83
83
  sourceId: record.data.entryID,
@@ -85,7 +85,7 @@ export default class FoodNomsTransformer extends ChronicleTransformer {
85
85
  object: meal,
86
86
  };
87
87
  const action = this.isDrink(record.data.name)
88
- ? { '@type': 'DrankAction', ...shared }
88
+ ? { '@type': 'DrinkAction', ...shared }
89
89
  : { '@type': 'EatAction', ...shared };
90
90
  return [action];
91
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chronicle.app/foodnoms",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -22,9 +22,9 @@
22
22
  "type": "module",
23
23
  "description": "Chronicle plugin for FoodNoms meal tracking data",
24
24
  "devDependencies": {
25
- "@chronicle.app/etl": "0.3.0",
26
- "@chronicle.app/schema": "0.3.0",
27
- "@chronicle.app/tsconfig": "0.3.0",
25
+ "@chronicle.app/etl": "0.4.0",
26
+ "@chronicle.app/schema": "0.4.0",
27
+ "@chronicle.app/tsconfig": "0.4.0",
28
28
  "@types/node": "^22.10.1",
29
29
  "typescript": "^5.7.2"
30
30
  },
@@ -39,8 +39,8 @@
39
39
  "registry": "https://registry.npmjs.org/"
40
40
  },
41
41
  "dependencies": {
42
- "@chronicle.app/etl-sqlite": "0.3.0",
43
- "@chronicle.app/icloud": "0.3.0",
42
+ "@chronicle.app/etl-sqlite": "0.4.0",
43
+ "@chronicle.app/icloud": "0.4.0",
44
44
  "zod": "^3.24.1"
45
45
  },
46
46
  "peerDependencies": {