@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 `
|
|
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 `
|
|
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
|
-
|
|
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': '
|
|
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
|
+
"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.
|
|
26
|
-
"@chronicle.app/schema": "0.
|
|
27
|
-
"@chronicle.app/tsconfig": "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.
|
|
43
|
-
"@chronicle.app/icloud": "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": {
|