skill-calorie 0.1.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.
Files changed (373) hide show
  1. package/dist/analysis/anomaly/common.d.ts +53 -0
  2. package/dist/analysis/anomaly/common.d.ts.map +1 -0
  3. package/dist/analysis/anomaly/common.js +69 -0
  4. package/dist/analysis/anomaly/common.js.map +1 -0
  5. package/dist/analysis/anomaly/diet.d.ts +8 -0
  6. package/dist/analysis/anomaly/diet.d.ts.map +1 -0
  7. package/dist/analysis/anomaly/diet.js +95 -0
  8. package/dist/analysis/anomaly/diet.js.map +1 -0
  9. package/dist/analysis/anomaly/exercise.d.ts +9 -0
  10. package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
  11. package/dist/analysis/anomaly/exercise.js +116 -0
  12. package/dist/analysis/anomaly/exercise.js.map +1 -0
  13. package/dist/analysis/anomaly/index.d.ts +19 -0
  14. package/dist/analysis/anomaly/index.d.ts.map +1 -0
  15. package/dist/analysis/anomaly/index.js +51 -0
  16. package/dist/analysis/anomaly/index.js.map +1 -0
  17. package/dist/analysis/anomaly/overall.d.ts +13 -0
  18. package/dist/analysis/anomaly/overall.d.ts.map +1 -0
  19. package/dist/analysis/anomaly/overall.js +128 -0
  20. package/dist/analysis/anomaly/overall.js.map +1 -0
  21. package/dist/analysis/anomaly/overall2.d.ts +5 -0
  22. package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
  23. package/dist/analysis/anomaly/overall2.js +94 -0
  24. package/dist/analysis/anomaly/overall2.js.map +1 -0
  25. package/dist/analysis/anomaly/weight.d.ts +8 -0
  26. package/dist/analysis/anomaly/weight.d.ts.map +1 -0
  27. package/dist/analysis/anomaly/weight.js +106 -0
  28. package/dist/analysis/anomaly/weight.js.map +1 -0
  29. package/dist/analysis/anomaly/weight2.d.ts +4 -0
  30. package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
  31. package/dist/analysis/anomaly/weight2.js +59 -0
  32. package/dist/analysis/anomaly/weight2.js.map +1 -0
  33. package/dist/analysis/contraindications.d.ts +63 -0
  34. package/dist/analysis/contraindications.d.ts.map +1 -0
  35. package/dist/analysis/contraindications.js +121 -0
  36. package/dist/analysis/contraindications.js.map +1 -0
  37. package/dist/analysis/cross.d.ts +75 -0
  38. package/dist/analysis/cross.d.ts.map +1 -0
  39. package/dist/analysis/cross.js +283 -0
  40. package/dist/analysis/cross.js.map +1 -0
  41. package/dist/analysis/dashboard.d.ts +18 -0
  42. package/dist/analysis/dashboard.d.ts.map +1 -0
  43. package/dist/analysis/dashboard.js +48 -0
  44. package/dist/analysis/dashboard.js.map +1 -0
  45. package/dist/analysis/deficit.d.ts +44 -0
  46. package/dist/analysis/deficit.d.ts.map +1 -0
  47. package/dist/analysis/deficit.js +54 -0
  48. package/dist/analysis/deficit.js.map +1 -0
  49. package/dist/analysis/diet.d.ts +76 -0
  50. package/dist/analysis/diet.d.ts.map +1 -0
  51. package/dist/analysis/diet.js +164 -0
  52. package/dist/analysis/diet.js.map +1 -0
  53. package/dist/analysis/exercise.d.ts +98 -0
  54. package/dist/analysis/exercise.d.ts.map +1 -0
  55. package/dist/analysis/exercise.js +298 -0
  56. package/dist/analysis/exercise.js.map +1 -0
  57. package/dist/analysis/exerciseReview.d.ts +36 -0
  58. package/dist/analysis/exerciseReview.d.ts.map +1 -0
  59. package/dist/analysis/exerciseReview.js +50 -0
  60. package/dist/analysis/exerciseReview.js.map +1 -0
  61. package/dist/analysis/precision.d.ts +15 -0
  62. package/dist/analysis/precision.d.ts.map +1 -0
  63. package/dist/analysis/precision.js +38 -0
  64. package/dist/analysis/precision.js.map +1 -0
  65. package/dist/analysis/result.d.ts +15 -0
  66. package/dist/analysis/result.d.ts.map +1 -0
  67. package/dist/analysis/result.js +13 -0
  68. package/dist/analysis/result.js.map +1 -0
  69. package/dist/analysis/review.d.ts +118 -0
  70. package/dist/analysis/review.d.ts.map +1 -0
  71. package/dist/analysis/review.js +195 -0
  72. package/dist/analysis/review.js.map +1 -0
  73. package/dist/analysis/series.d.ts +42 -0
  74. package/dist/analysis/series.d.ts.map +1 -0
  75. package/dist/analysis/series.js +127 -0
  76. package/dist/analysis/series.js.map +1 -0
  77. package/dist/analysis/simulate.d.ts +43 -0
  78. package/dist/analysis/simulate.d.ts.map +1 -0
  79. package/dist/analysis/simulate.js +109 -0
  80. package/dist/analysis/simulate.js.map +1 -0
  81. package/dist/analysis/simulate2.d.ts +65 -0
  82. package/dist/analysis/simulate2.d.ts.map +1 -0
  83. package/dist/analysis/simulate2.js +173 -0
  84. package/dist/analysis/simulate2.js.map +1 -0
  85. package/dist/analysis/trend.d.ts +39 -0
  86. package/dist/analysis/trend.d.ts.map +1 -0
  87. package/dist/analysis/trend.js +48 -0
  88. package/dist/analysis/trend.js.map +1 -0
  89. package/dist/analysis/utils.d.ts +17 -0
  90. package/dist/analysis/utils.d.ts.map +1 -0
  91. package/dist/analysis/utils.js +52 -0
  92. package/dist/analysis/utils.js.map +1 -0
  93. package/dist/analysis/volatility.d.ts +43 -0
  94. package/dist/analysis/volatility.d.ts.map +1 -0
  95. package/dist/analysis/volatility.js +96 -0
  96. package/dist/analysis/volatility.js.map +1 -0
  97. package/dist/analysis/weight.d.ts +86 -0
  98. package/dist/analysis/weight.d.ts.map +1 -0
  99. package/dist/analysis/weight.js +219 -0
  100. package/dist/analysis/weight.js.map +1 -0
  101. package/dist/analysis/weightCompare.d.ts +63 -0
  102. package/dist/analysis/weightCompare.d.ts.map +1 -0
  103. package/dist/analysis/weightCompare.js +212 -0
  104. package/dist/analysis/weightCompare.js.map +1 -0
  105. package/dist/analysis/weightCompare2.d.ts +63 -0
  106. package/dist/analysis/weightCompare2.d.ts.map +1 -0
  107. package/dist/analysis/weightCompare2.js +211 -0
  108. package/dist/analysis/weightCompare2.js.map +1 -0
  109. package/dist/analysis/weightCompare3.d.ts +13 -0
  110. package/dist/analysis/weightCompare3.d.ts.map +1 -0
  111. package/dist/analysis/weightCompare3.js +199 -0
  112. package/dist/analysis/weightCompare3.js.map +1 -0
  113. package/dist/cli/cmd_read.d.ts +8 -0
  114. package/dist/cli/cmd_read.d.ts.map +1 -0
  115. package/dist/cli/cmd_read.js +719 -0
  116. package/dist/cli/cmd_read.js.map +1 -0
  117. package/dist/cli/keys.d.ts +333 -0
  118. package/dist/cli/keys.d.ts.map +1 -0
  119. package/dist/cli/keys.js +103 -0
  120. package/dist/cli/keys.js.map +1 -0
  121. package/dist/cli/write.d.ts +24 -0
  122. package/dist/cli/write.d.ts.map +1 -0
  123. package/dist/cli/write.js +832 -0
  124. package/dist/cli/write.js.map +1 -0
  125. package/dist/fetch/audit.d.ts +25 -0
  126. package/dist/fetch/audit.d.ts.map +1 -0
  127. package/dist/fetch/audit.js +46 -0
  128. package/dist/fetch/audit.js.map +1 -0
  129. package/dist/fetch/batch.d.ts +68 -0
  130. package/dist/fetch/batch.d.ts.map +1 -0
  131. package/dist/fetch/batch.js +183 -0
  132. package/dist/fetch/batch.js.map +1 -0
  133. package/dist/fetch/body.d.ts +89 -0
  134. package/dist/fetch/body.d.ts.map +1 -0
  135. package/dist/fetch/body.js +217 -0
  136. package/dist/fetch/body.js.map +1 -0
  137. package/dist/fetch/cli.d.ts +3 -0
  138. package/dist/fetch/cli.d.ts.map +1 -0
  139. package/dist/fetch/cli.js +195 -0
  140. package/dist/fetch/cli.js.map +1 -0
  141. package/dist/fetch/cross-skill.d.ts +29 -0
  142. package/dist/fetch/cross-skill.d.ts.map +1 -0
  143. package/dist/fetch/cross-skill.js +42 -0
  144. package/dist/fetch/cross-skill.js.map +1 -0
  145. package/dist/fetch/db.d.ts +5 -0
  146. package/dist/fetch/db.d.ts.map +1 -0
  147. package/dist/fetch/db.js +4 -0
  148. package/dist/fetch/db.js.map +1 -0
  149. package/dist/fetch/diet.d.ts +174 -0
  150. package/dist/fetch/diet.d.ts.map +1 -0
  151. package/dist/fetch/diet.js +239 -0
  152. package/dist/fetch/diet.js.map +1 -0
  153. package/dist/fetch/errors.d.ts +5 -0
  154. package/dist/fetch/errors.d.ts.map +1 -0
  155. package/dist/fetch/errors.js +8 -0
  156. package/dist/fetch/errors.js.map +1 -0
  157. package/dist/fetch/exercise.d.ts +72 -0
  158. package/dist/fetch/exercise.d.ts.map +1 -0
  159. package/dist/fetch/exercise.js +270 -0
  160. package/dist/fetch/exercise.js.map +1 -0
  161. package/dist/fetch/goal.d.ts +48 -0
  162. package/dist/fetch/goal.d.ts.map +1 -0
  163. package/dist/fetch/goal.js +73 -0
  164. package/dist/fetch/goal.js.map +1 -0
  165. package/dist/fetch/goalHistory.d.ts +24 -0
  166. package/dist/fetch/goalHistory.d.ts.map +1 -0
  167. package/dist/fetch/goalHistory.js +51 -0
  168. package/dist/fetch/goalHistory.js.map +1 -0
  169. package/dist/fetch/history.d.ts +28 -0
  170. package/dist/fetch/history.d.ts.map +1 -0
  171. package/dist/fetch/history.js +29 -0
  172. package/dist/fetch/history.js.map +1 -0
  173. package/dist/fetch/index.d.ts +23 -0
  174. package/dist/fetch/index.d.ts.map +1 -0
  175. package/dist/fetch/index.js +16 -0
  176. package/dist/fetch/index.js.map +1 -0
  177. package/dist/fetch/nutritionGoal.d.ts +115 -0
  178. package/dist/fetch/nutritionGoal.d.ts.map +1 -0
  179. package/dist/fetch/nutritionGoal.js +154 -0
  180. package/dist/fetch/nutritionGoal.js.map +1 -0
  181. package/dist/fetch/photos.d.ts +76 -0
  182. package/dist/fetch/photos.d.ts.map +1 -0
  183. package/dist/fetch/photos.js +193 -0
  184. package/dist/fetch/photos.js.map +1 -0
  185. package/dist/fetch/plan.d.ts +145 -0
  186. package/dist/fetch/plan.d.ts.map +1 -0
  187. package/dist/fetch/plan.js +258 -0
  188. package/dist/fetch/plan.js.map +1 -0
  189. package/dist/fetch/products.d.ts +62 -0
  190. package/dist/fetch/products.d.ts.map +1 -0
  191. package/dist/fetch/products.js +73 -0
  192. package/dist/fetch/products.js.map +1 -0
  193. package/dist/fetch/profile.d.ts +46 -0
  194. package/dist/fetch/profile.d.ts.map +1 -0
  195. package/dist/fetch/profile.js +105 -0
  196. package/dist/fetch/profile.js.map +1 -0
  197. package/dist/fetch/shapes.d.ts +41 -0
  198. package/dist/fetch/shapes.d.ts.map +1 -0
  199. package/dist/fetch/shapes.js +38 -0
  200. package/dist/fetch/shapes.js.map +1 -0
  201. package/dist/fetch/validate.d.ts +11 -0
  202. package/dist/fetch/validate.d.ts.map +1 -0
  203. package/dist/fetch/validate.js +64 -0
  204. package/dist/fetch/validate.js.map +1 -0
  205. package/dist/fetch/weight.d.ts +109 -0
  206. package/dist/fetch/weight.d.ts.map +1 -0
  207. package/dist/fetch/weight.js +210 -0
  208. package/dist/fetch/weight.js.map +1 -0
  209. package/dist/fetch/xunji-catalog.d.ts +17 -0
  210. package/dist/fetch/xunji-catalog.d.ts.map +1 -0
  211. package/dist/fetch/xunji-catalog.js +57 -0
  212. package/dist/fetch/xunji-catalog.js.map +1 -0
  213. package/dist/index.d.ts +17 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +12 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/kcal.d.ts +21 -0
  218. package/dist/kcal.d.ts.map +1 -0
  219. package/dist/kcal.js +27 -0
  220. package/dist/kcal.js.map +1 -0
  221. package/dist/migrate/migrate.d.ts +71 -0
  222. package/dist/migrate/migrate.d.ts.map +1 -0
  223. package/dist/migrate/migrate.js +450 -0
  224. package/dist/migrate/migrate.js.map +1 -0
  225. package/dist/paths.d.ts +6 -0
  226. package/dist/paths.d.ts.map +1 -0
  227. package/dist/paths.js +34 -0
  228. package/dist/paths.js.map +1 -0
  229. package/dist/render/analysisPlate.d.ts +49 -0
  230. package/dist/render/analysisPlate.d.ts.map +1 -0
  231. package/dist/render/analysisPlate.js +149 -0
  232. package/dist/render/analysisPlate.js.map +1 -0
  233. package/dist/render/bodyPlate.d.ts +55 -0
  234. package/dist/render/bodyPlate.d.ts.map +1 -0
  235. package/dist/render/bodyPlate.js +97 -0
  236. package/dist/render/bodyPlate.js.map +1 -0
  237. package/dist/render/diet.d.ts +47 -0
  238. package/dist/render/diet.d.ts.map +1 -0
  239. package/dist/render/diet.js +94 -0
  240. package/dist/render/diet.js.map +1 -0
  241. package/dist/render/envelope.d.ts +60 -0
  242. package/dist/render/envelope.d.ts.map +1 -0
  243. package/dist/render/envelope.js +111 -0
  244. package/dist/render/envelope.js.map +1 -0
  245. package/dist/render/errors.d.ts +10 -0
  246. package/dist/render/errors.d.ts.map +1 -0
  247. package/dist/render/errors.js +9 -0
  248. package/dist/render/errors.js.map +1 -0
  249. package/dist/render/exercise.d.ts +20 -0
  250. package/dist/render/exercise.d.ts.map +1 -0
  251. package/dist/render/exercise.js +32 -0
  252. package/dist/render/exercise.js.map +1 -0
  253. package/dist/render/goal.d.ts +24 -0
  254. package/dist/render/goal.d.ts.map +1 -0
  255. package/dist/render/goal.js +23 -0
  256. package/dist/render/goal.js.map +1 -0
  257. package/dist/render/goalExtra.d.ts +45 -0
  258. package/dist/render/goalExtra.d.ts.map +1 -0
  259. package/dist/render/goalExtra.js +94 -0
  260. package/dist/render/goalExtra.js.map +1 -0
  261. package/dist/render/goalPlate.d.ts +66 -0
  262. package/dist/render/goalPlate.d.ts.map +1 -0
  263. package/dist/render/goalPlate.js +110 -0
  264. package/dist/render/goalPlate.js.map +1 -0
  265. package/dist/render/health.d.ts +21 -0
  266. package/dist/render/health.d.ts.map +1 -0
  267. package/dist/render/health.js +41 -0
  268. package/dist/render/health.js.map +1 -0
  269. package/dist/render/help.d.ts +18 -0
  270. package/dist/render/help.d.ts.map +1 -0
  271. package/dist/render/help.js +58 -0
  272. package/dist/render/help.js.map +1 -0
  273. package/dist/render/home.d.ts +30 -0
  274. package/dist/render/home.d.ts.map +1 -0
  275. package/dist/render/home.js +73 -0
  276. package/dist/render/home.js.map +1 -0
  277. package/dist/render/html.d.ts +66 -0
  278. package/dist/render/html.d.ts.map +1 -0
  279. package/dist/render/html.js +510 -0
  280. package/dist/render/html.js.map +1 -0
  281. package/dist/render/index.d.ts +47 -0
  282. package/dist/render/index.d.ts.map +1 -0
  283. package/dist/render/index.js +26 -0
  284. package/dist/render/index.js.map +1 -0
  285. package/dist/render/insightPlate.d.ts +55 -0
  286. package/dist/render/insightPlate.d.ts.map +1 -0
  287. package/dist/render/insightPlate.js +97 -0
  288. package/dist/render/insightPlate.js.map +1 -0
  289. package/dist/render/library.d.ts +32 -0
  290. package/dist/render/library.d.ts.map +1 -0
  291. package/dist/render/library.js +54 -0
  292. package/dist/render/library.js.map +1 -0
  293. package/dist/render/photo.d.ts +101 -0
  294. package/dist/render/photo.d.ts.map +1 -0
  295. package/dist/render/photo.js +241 -0
  296. package/dist/render/photo.js.map +1 -0
  297. package/dist/render/planPlate.d.ts +40 -0
  298. package/dist/render/planPlate.d.ts.map +1 -0
  299. package/dist/render/planPlate.js +72 -0
  300. package/dist/render/planPlate.js.map +1 -0
  301. package/dist/render/profilePlate.d.ts +17 -0
  302. package/dist/render/profilePlate.d.ts.map +1 -0
  303. package/dist/render/profilePlate.js +18 -0
  304. package/dist/render/profilePlate.js.map +1 -0
  305. package/dist/render/ranking.d.ts +22 -0
  306. package/dist/render/ranking.d.ts.map +1 -0
  307. package/dist/render/ranking.js +63 -0
  308. package/dist/render/ranking.js.map +1 -0
  309. package/dist/render/receipt.d.ts +71 -0
  310. package/dist/render/receipt.d.ts.map +1 -0
  311. package/dist/render/receipt.js +65 -0
  312. package/dist/render/receipt.js.map +1 -0
  313. package/dist/render/weightPlate.d.ts +54 -0
  314. package/dist/render/weightPlate.d.ts.map +1 -0
  315. package/dist/render/weightPlate.js +110 -0
  316. package/dist/render/weightPlate.js.map +1 -0
  317. package/dist/schema.d.ts +25 -0
  318. package/dist/schema.d.ts.map +1 -0
  319. package/dist/schema.js +281 -0
  320. package/dist/schema.js.map +1 -0
  321. package/dist/triggers/help-lookup.d.ts +28 -0
  322. package/dist/triggers/help-lookup.d.ts.map +1 -0
  323. package/dist/triggers/help-lookup.js +163 -0
  324. package/dist/triggers/help-lookup.js.map +1 -0
  325. package/dist/triggers/index.d.ts +24 -0
  326. package/dist/triggers/index.d.ts.map +1 -0
  327. package/dist/triggers/index.js +78 -0
  328. package/dist/triggers/index.js.map +1 -0
  329. package/dist/triggers/scene-01-home.d.ts +4 -0
  330. package/dist/triggers/scene-01-home.d.ts.map +1 -0
  331. package/dist/triggers/scene-01-home.js +13 -0
  332. package/dist/triggers/scene-01-home.js.map +1 -0
  333. package/dist/triggers/scene-02-diet.d.ts +4 -0
  334. package/dist/triggers/scene-02-diet.d.ts.map +1 -0
  335. package/dist/triggers/scene-02-diet.js +74 -0
  336. package/dist/triggers/scene-02-diet.js.map +1 -0
  337. package/dist/triggers/scene-03-weight.d.ts +4 -0
  338. package/dist/triggers/scene-03-weight.d.ts.map +1 -0
  339. package/dist/triggers/scene-03-weight.js +62 -0
  340. package/dist/triggers/scene-03-weight.js.map +1 -0
  341. package/dist/triggers/scene-04-exercise.d.ts +4 -0
  342. package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
  343. package/dist/triggers/scene-04-exercise.js +43 -0
  344. package/dist/triggers/scene-04-exercise.js.map +1 -0
  345. package/dist/triggers/scene-05-workout.d.ts +4 -0
  346. package/dist/triggers/scene-05-workout.d.ts.map +1 -0
  347. package/dist/triggers/scene-05-workout.js +36 -0
  348. package/dist/triggers/scene-05-workout.js.map +1 -0
  349. package/dist/triggers/scene-06-goal.d.ts +4 -0
  350. package/dist/triggers/scene-06-goal.d.ts.map +1 -0
  351. package/dist/triggers/scene-06-goal.js +29 -0
  352. package/dist/triggers/scene-06-goal.js.map +1 -0
  353. package/dist/triggers/scene-07-profile.d.ts +4 -0
  354. package/dist/triggers/scene-07-profile.d.ts.map +1 -0
  355. package/dist/triggers/scene-07-profile.js +8 -0
  356. package/dist/triggers/scene-07-profile.js.map +1 -0
  357. package/dist/triggers/scene-08-body.d.ts +4 -0
  358. package/dist/triggers/scene-08-body.d.ts.map +1 -0
  359. package/dist/triggers/scene-08-body.js +17 -0
  360. package/dist/triggers/scene-08-body.js.map +1 -0
  361. package/dist/triggers/scene-09-photo.d.ts +4 -0
  362. package/dist/triggers/scene-09-photo.d.ts.map +1 -0
  363. package/dist/triggers/scene-09-photo.js +14 -0
  364. package/dist/triggers/scene-09-photo.js.map +1 -0
  365. package/dist/triggers/scene-10-analysis.d.ts +4 -0
  366. package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
  367. package/dist/triggers/scene-10-analysis.js +180 -0
  368. package/dist/triggers/scene-10-analysis.js.map +1 -0
  369. package/dist/triggers/types.d.ts +66 -0
  370. package/dist/triggers/types.d.ts.map +1 -0
  371. package/dist/triggers/types.js +3 -0
  372. package/dist/triggers/types.js.map +1 -0
  373. package/package.json +35 -0
@@ -0,0 +1,16 @@
1
+ /** 取数层 barrel:T3 饮食 / 体重 / 运动 / 身体 / envelope 结构段 + T6 导入 / 历史 / 跨技能只读。 */
2
+ export { FetchError } from './errors.js';
3
+ export * from './diet.js';
4
+ export * from './weight.js';
5
+ export * from './exercise.js';
6
+ export * from './body.js';
7
+ export { CALORIE_SKILL, calorieKey, fetchPayload, KEYS } from './shapes.js';
8
+ // T6 #25 · 批量导入 / 近日 history / 跨技能只读 / 训记 catalog / 计划审计
9
+ export { REQUIRED_FIELDS, OPTIONAL_FIELDS, NUMERIC_FIELDS, validateRecord } from './validate.js';
10
+ export { readJsonl, dedupeKey, checkDuplicate, importProducts, validateFile, dedupeReport, exportBySource, } from './batch.js';
11
+ export { getCalorieHistory, weightSeries } from './history.js';
12
+ export { readSkill, requireOk } from './cross-skill.js';
13
+ export { getProfile, setProfile, setActivityLevel, updateProfile, normalizeActivityLevel, normalizeGender, PROFILE_UPDATABLE, ACTIVITY_ALIASES } from './profile.js';
14
+ export { DEFAULT_CATALOG_PATH, loadCatalog, suggestSimilar, verifyMovementName, verifyMany } from './xunji-catalog.js';
15
+ export { collectPlanNames, auditPlanNames } from './audit.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fetch/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5E,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjG,OAAO,EACL,SAAS,EACT,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,sBAAsB,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErK,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEvH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,115 @@
1
+ /** T4 #23 · nutrition_goal 取数+写数(对照老家 scripts/nutrition_goal.py)。
2
+ *
3
+ * 读:getNutritionGoal(无行回 null,老家 Row-or-None 同义)。
4
+ * 写:setNutritionGoal(4 参必填 + 饮水可选 + 自洽 diff 回传,不 print)。
5
+ * 算:recommendNutritionGoal / recommendWaterGoal(纯算式对照;activity 系数与
6
+ * 体重缺省走注入(T5 analysis / T3 weight_log 归属,缺省标记 missing,不静默编造)。
7
+ */
8
+ import type { DatabaseSync } from 'node:sqlite';
9
+ export interface NutritionGoalRow {
10
+ id: number;
11
+ calorie_goal: number;
12
+ protein_goal: number | null;
13
+ carbs_goal: number | null;
14
+ fat_goal: number | null;
15
+ weight_goal: number | null;
16
+ goal_deadline: string | null;
17
+ water_goal: number | null;
18
+ updated_at: string | null;
19
+ }
20
+ export interface SetGoalInput {
21
+ calorie: unknown;
22
+ protein: unknown;
23
+ carbs: unknown;
24
+ fat: unknown;
25
+ water?: unknown;
26
+ }
27
+ export interface SetGoalResult {
28
+ calorieGoal: number;
29
+ proteinGoal: number;
30
+ carbsGoal: number;
31
+ fatGoal: number;
32
+ waterGoal: number | null;
33
+ diffKcal: number;
34
+ consistent: boolean;
35
+ }
36
+ export declare function getNutritionGoal(db: DatabaseSync): NutritionGoalRow | null;
37
+ export declare function setNutritionGoal(db: DatabaseSync, input: SetGoalInput): SetGoalResult;
38
+ export declare const NUTRI_PROFILES: {
39
+ readonly cut: {
40
+ readonly calorieAdj: -500;
41
+ readonly proteinGPerKg: 2;
42
+ readonly waterMlPerKg: 35;
43
+ readonly fatPct: 0.25;
44
+ };
45
+ readonly maintain: {
46
+ readonly calorieAdj: 0;
47
+ readonly proteinGPerKg: 1.6;
48
+ readonly waterMlPerKg: 30;
49
+ readonly fatPct: 0.3;
50
+ };
51
+ readonly bulk: {
52
+ readonly calorieAdj: 400;
53
+ readonly proteinGPerKg: 1.8;
54
+ readonly waterMlPerKg: 30;
55
+ readonly fatPct: 0.25;
56
+ };
57
+ };
58
+ export type NutriProfile = keyof typeof NUTRI_PROFILES;
59
+ export declare const NUTRI_PROFILE_LABELS: Record<NutriProfile, string>;
60
+ export declare const NUTRI_PROFILE_WEEKLY_RATE: Record<NutriProfile, number>;
61
+ export interface RecommendInput {
62
+ profile?: NutriProfile;
63
+ weightKg?: number | null;
64
+ heightCm?: number | null;
65
+ age?: number | null;
66
+ gender?: string | null;
67
+ activityFactor?: number | null;
68
+ }
69
+ export interface RecommendResult {
70
+ profile: NutriProfile;
71
+ profileLabel: string;
72
+ tdee: number;
73
+ bmr: number;
74
+ calorieGoal: number;
75
+ proteinGoal: number;
76
+ carbsGoal: number;
77
+ fatGoal: number;
78
+ waterGoal: number;
79
+ weeklyRateKg: number;
80
+ basis: {
81
+ weightKg: number;
82
+ heightCm: number;
83
+ age: number;
84
+ gender: string;
85
+ };
86
+ planReasons: string[];
87
+ missing: string[];
88
+ selfCheck: {
89
+ calculatedKcal: number;
90
+ diffKcal: number;
91
+ };
92
+ }
93
+ export declare function latestWeightKg(db: DatabaseSync): number | null;
94
+ export declare function recommendNutritionGoal(db: DatabaseSync, opts?: RecommendInput): RecommendResult;
95
+ export interface WaterRecommendInput {
96
+ weightKg?: number | null;
97
+ season?: '夏' | '冬' | null;
98
+ month?: number | null;
99
+ }
100
+ export declare function recommendWaterGoal(db: DatabaseSync, opts?: WaterRecommendInput): {
101
+ weightKg: number;
102
+ season: '夏' | '冬';
103
+ mlPerKg: number;
104
+ recommendedWaterMl: number;
105
+ oldWaterGoal: number | null;
106
+ basis: string;
107
+ };
108
+ export declare function updateWaterGoal(db: DatabaseSync, waterGoal: unknown): {
109
+ id: number;
110
+ updatedAt: string | null;
111
+ rowsAffected: number;
112
+ oldWaterGoal: number | null;
113
+ newWaterGoal: number;
114
+ };
115
+ //# sourceMappingURL=nutritionGoal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nutritionGoal.d.ts","sourceRoot":"","sources":["../../src/fetch/nutritionGoal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ import { FetchError } from './errors.js';
2
+ function toInt(v, field) {
3
+ const n = typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' ? Number(v) : NaN;
4
+ if (!Number.isFinite(n))
5
+ throw new FetchError(field + '必须是数字');
6
+ return Math.trunc(n);
7
+ }
8
+ export function getNutritionGoal(db) {
9
+ const row = db.prepare('SELECT * FROM daily_goal WHERE id = 1').get();
10
+ return row ?? null;
11
+ }
12
+ export function setNutritionGoal(db, input) {
13
+ if (input.protein === undefined || input.carbs === undefined || input.fat === undefined) {
14
+ throw new FetchError('goal 必须 4 个参数全传(热量/蛋白/碳水/脂肪)');
15
+ }
16
+ const calorie = toInt(input.calorie, '热量目标');
17
+ const protein = toInt(input.protein, '蛋白质目标');
18
+ const carbs = toInt(input.carbs, '碳水目标');
19
+ const fat = toInt(input.fat, '脂肪目标');
20
+ if (calorie <= 0)
21
+ throw new FetchError('热量目标必须为正数');
22
+ if (protein < 0 || carbs < 0 || fat < 0)
23
+ throw new FetchError('营养目标不能为负数');
24
+ let water = null;
25
+ if (input.water !== undefined && input.water !== null) {
26
+ water = toInt(input.water, '饮水目标');
27
+ if (water < 0)
28
+ throw new FetchError('饮水目标不能为负数');
29
+ }
30
+ const diff = protein * 4 + carbs * 4 + fat * 9 - calorie;
31
+ if (water !== null) {
32
+ db.prepare('INSERT OR REPLACE INTO daily_goal (id, calorie_goal, protein_goal, carbs_goal, fat_goal, water_goal, updated_at)' +
33
+ ' VALUES (1, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)').run(calorie, protein, carbs, fat, water);
34
+ }
35
+ else {
36
+ db.prepare('INSERT OR REPLACE INTO daily_goal (id, calorie_goal, protein_goal, carbs_goal, fat_goal, updated_at)' +
37
+ ' VALUES (1, ?, ?, ?, ?, CURRENT_TIMESTAMP)').run(calorie, protein, carbs, fat);
38
+ }
39
+ const row = getNutritionGoal(db);
40
+ return {
41
+ calorieGoal: calorie,
42
+ proteinGoal: protein,
43
+ carbsGoal: carbs,
44
+ fatGoal: fat,
45
+ waterGoal: row?.water_goal ?? water,
46
+ diffKcal: diff,
47
+ consistent: Math.abs(diff) <= 50,
48
+ };
49
+ }
50
+ export const NUTRI_PROFILES = {
51
+ cut: { calorieAdj: -500, proteinGPerKg: 2.0, waterMlPerKg: 35, fatPct: 0.25 },
52
+ maintain: { calorieAdj: 0, proteinGPerKg: 1.6, waterMlPerKg: 30, fatPct: 0.3 },
53
+ bulk: { calorieAdj: 400, proteinGPerKg: 1.8, waterMlPerKg: 30, fatPct: 0.25 },
54
+ };
55
+ export const NUTRI_PROFILE_LABELS = { cut: '减脂', maintain: '维持', bulk: '增肌' };
56
+ export const NUTRI_PROFILE_WEEKLY_RATE = { cut: 0.5, maintain: 0.0, bulk: 0.4 };
57
+ export function latestWeightKg(db) {
58
+ const row = db
59
+ .prepare('SELECT weight_kg FROM weight_log ORDER BY date DESC, id DESC LIMIT 1')
60
+ .get();
61
+ return row?.weight_kg ?? null;
62
+ }
63
+ export function recommendNutritionGoal(db, opts = {}) {
64
+ const profile = opts.profile ?? 'cut';
65
+ const p = NUTRI_PROFILES[profile];
66
+ if (!p)
67
+ throw new FetchError('profile 非法(cut/maintain/bulk): ' + String(opts.profile));
68
+ const missing = [];
69
+ let weight = opts.weightKg ?? latestWeightKg(db);
70
+ const prof = db
71
+ .prepare('SELECT age, gender, height_cm, activity_level FROM user_profile WHERE id = 1')
72
+ .get();
73
+ let height = opts.heightCm ?? prof?.height_cm ?? null;
74
+ let age = opts.age ?? prof?.age ?? null;
75
+ let gender = opts.gender ?? prof?.gender ?? null;
76
+ if (!prof)
77
+ missing.push('年龄', '性别', '身高');
78
+ else {
79
+ if (prof.age === null || prof.age === undefined)
80
+ missing.push('年龄');
81
+ if (!prof.gender)
82
+ missing.push('性别');
83
+ if (prof.height_cm === null || prof.height_cm === undefined)
84
+ missing.push('身高');
85
+ }
86
+ if (weight === null || weight === undefined)
87
+ missing.push('体重');
88
+ const w = weight ?? 70.0;
89
+ const h = height ?? 175.0;
90
+ const a = age ?? 30;
91
+ const g = gender ?? 'male';
92
+ const factor = opts.activityFactor ?? 1.55;
93
+ const bmr = 10 * w + 6.25 * h - 5 * a + (g === 'male' ? 5 : -161);
94
+ const tdee = bmr * factor;
95
+ const cal = Math.trunc(tdee + p.calorieAdj);
96
+ const protein = Math.trunc(w * p.proteinGPerKg);
97
+ const fat = Math.trunc((cal * p.fatPct) / 9);
98
+ const carbs = Math.max(Math.trunc((cal - protein * 4 - fat * 9) / 4), 0);
99
+ const water = Math.trunc(w * p.waterMlPerKg);
100
+ const calculated = protein * 4 + carbs * 4 + fat * 9;
101
+ const diff = calculated - cal;
102
+ const reasons = [
103
+ NUTRI_PROFILE_LABELS[profile] + '模板:TDEE ' + Math.trunc(tdee) + ' 卡 × 热量调整 ' + (p.calorieAdj >= 0 ? '+' : '') + p.calorieAdj + ' 卡 → 每日 ' + cal + ' 卡',
104
+ '蛋白 ' + protein + ' g(体重 ' + w.toFixed(1) + ' kg × ' + p.proteinGPerKg + ' g/kg)',
105
+ '脂肪 ' + fat + ' g(占热量 ' + Math.trunc(p.fatPct * 100) + '%)· 碳水 ' + carbs + ' g(余量)',
106
+ '饮水 ' + water + ' ml(体重 × ' + p.waterMlPerKg + ' ml/kg)',
107
+ '预计每周减重速率 ' + NUTRI_PROFILE_WEEKLY_RATE[profile].toFixed(1) + ' kg(Δ' + cal + ' - TDEE ' + Math.trunc(tdee) + ')',
108
+ ];
109
+ if (Math.abs(diff) > 50)
110
+ reasons.push('⚠️ 自洽性校验:宏量换算 ' + calculated + ' 卡,与热量目标差 ' + (diff >= 0 ? '+' : '') + diff + ' 卡(>50 建议复核)');
111
+ return {
112
+ profile,
113
+ profileLabel: NUTRI_PROFILE_LABELS[profile],
114
+ tdee: Math.trunc(tdee),
115
+ bmr: Math.trunc(bmr),
116
+ calorieGoal: cal,
117
+ proteinGoal: protein,
118
+ carbsGoal: carbs,
119
+ fatGoal: fat,
120
+ waterGoal: water,
121
+ weeklyRateKg: NUTRI_PROFILE_WEEKLY_RATE[profile],
122
+ basis: { weightKg: Math.round(w * 10) / 10, heightCm: h, age: a, gender: g },
123
+ planReasons: reasons,
124
+ missing,
125
+ selfCheck: { calculatedKcal: calculated, diffKcal: diff },
126
+ };
127
+ }
128
+ export function recommendWaterGoal(db, opts = {}) {
129
+ const w = opts.weightKg ?? latestWeightKg(db) ?? 70.0;
130
+ const month = opts.month ?? new Date().getMonth() + 1;
131
+ const season = opts.season ?? (month >= 6 && month <= 9 ? '夏' : '冬');
132
+ const mlPerKg = season === '夏' ? 35 : 30;
133
+ const old = getNutritionGoal(db)?.water_goal ?? null;
134
+ return {
135
+ weightKg: Math.round(w * 10) / 10,
136
+ season,
137
+ mlPerKg,
138
+ recommendedWaterMl: Math.trunc(w * mlPerKg),
139
+ oldWaterGoal: old,
140
+ basis: '体重 ' + w.toFixed(1) + ' kg × ' + mlPerKg + ' ml/kg(' + (season === '夏' ? '夏季偏高' : '冬季常规') + ')',
141
+ };
142
+ }
143
+ export function updateWaterGoal(db, waterGoal) {
144
+ const water = toInt(waterGoal, '饮水目标');
145
+ if (water < 0)
146
+ throw new FetchError('饮水目标不能为负数');
147
+ const old = getNutritionGoal(db)?.water_goal ?? null;
148
+ const upd = db
149
+ .prepare('UPDATE daily_goal SET water_goal = ?, updated_at = CURRENT_TIMESTAMP WHERE id = 1')
150
+ .run(water);
151
+ const row = db.prepare('SELECT id, updated_at FROM daily_goal WHERE id = 1').get();
152
+ return { id: row?.id ?? 1, updatedAt: row?.updated_at ?? null, rowsAffected: Number(upd.changes), oldWaterGoal: old, newWaterGoal: water };
153
+ }
154
+ //# sourceMappingURL=nutritionGoal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nutritionGoal.js","sourceRoot":"","sources":["../../src/fetch/nutritionGoal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /** T4 #23 · body_photo_tracker 取数+写数(对照老家 scripts/body_photo_tracker.py)。
2
+ *
3
+ * 铁律:照片二进制只存路径 + 元数据(body_photos.photo_path 仅文件名,目录由
4
+ * CALORIE_PHOTOS_DIR 解析;缺失直接抛,不静默落盘)。gif 规划器只出任务描述
5
+ * (planGif),不跑图像处理。getLatestWeight 归 T3(weight_log),此处不碰。
6
+ */
7
+ import type { DatabaseSync } from 'node:sqlite';
8
+ export declare const TAG_SEP = ",";
9
+ export declare const TAG_MAX_LEN = 20;
10
+ export declare const TAG_MAX_COUNT = 10;
11
+ /** '正面, 侧面' → ['正面', '侧面'](去空白/去空项/去重保序)。 */
12
+ export declare function parseTags(tagStr: string | null | undefined): string[];
13
+ export declare function serializeTags(tags: string[]): string;
14
+ /** 硬规则:非空 + 单个 ≤20 + 数量 ≤10(非法即抛)。 */
15
+ export declare function validateTags(tags: string[]): string[];
16
+ export declare function tagsContain(tagStr: string | null | undefined, tag: string): boolean;
17
+ /** 照片目录解析:显式传参 > CALORIE_PHOTOS_DIR;缺失抛(不静默落盘)。 */
18
+ export declare function resolvePhotosDir(dir?: string | null): string;
19
+ export interface PhotoRow {
20
+ id: number;
21
+ date: string;
22
+ time: string | null;
23
+ photo_path: string;
24
+ tag: string;
25
+ note: string | null;
26
+ created_at: string | null;
27
+ tag_list: string[];
28
+ }
29
+ export declare function getPhotoRow(db: DatabaseSync, id: number): PhotoRow | null;
30
+ export interface ListPhotosFilter {
31
+ days?: number;
32
+ tag?: string | null;
33
+ dateFrom?: string | null;
34
+ dateTo?: string | null;
35
+ limit?: number | null;
36
+ today?: string;
37
+ }
38
+ export declare function listPhotos(db: DatabaseSync, filter?: ListPhotosFilter): PhotoRow[];
39
+ export declare function daysSinceTagPhoto(db: DatabaseSync, tag: string, beforeDate: string): number | null;
40
+ export interface AddPhotosInput {
41
+ srcPaths: string[];
42
+ tag: string;
43
+ note?: string;
44
+ today?: string;
45
+ nowTime?: string;
46
+ }
47
+ /** 添加照片:文件复制进目录 + 落库(仅文件名入库)。不存在的源文件跳过。 */
48
+ export declare function addPhotos(db: DatabaseSync, photosDir: string, input: AddPhotosInput): Array<{
49
+ id: number;
50
+ file: string;
51
+ }>;
52
+ export declare function deletePhoto(db: DatabaseSync, photosDir: string, id: number): {
53
+ deleted: boolean;
54
+ fileDeleted: boolean;
55
+ };
56
+ export declare function updateTag(db: DatabaseSync, id: number, newTag: string): boolean;
57
+ /** 追加标签(判重);返回新增标签数(不存在的照片回 0)。 */
58
+ export declare function tagAdd(db: DatabaseSync, id: number, tag: string): number;
59
+ /** 移除单个标签(至少保留 1 个;一次只删 1 个)。 */
60
+ export declare function tagRemove(db: DatabaseSync, id: number, tag: string): boolean;
61
+ export interface GifPlanInput {
62
+ tag: string;
63
+ dateFrom?: string | null;
64
+ dateTo?: string | null;
65
+ days?: number | null;
66
+ }
67
+ /** gif 规划器:只出任务描述(起止、张数、标签),不跑图像处理、不碰二进制。 */
68
+ export declare function planGif(db: DatabaseSync, input: GifPlanInput): {
69
+ task: 'generate_gif';
70
+ tag: string;
71
+ dateFrom: string | null;
72
+ dateTo: string | null;
73
+ photoCount: number;
74
+ photoIds: number[];
75
+ };
76
+ //# sourceMappingURL=photos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"photos.d.ts","sourceRoot":"","sources":["../../src/fetch/photos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs';
2
+ import { basename, join, resolve } from 'node:path';
3
+ import { FetchError } from './errors.js';
4
+ export const TAG_SEP = ',';
5
+ export const TAG_MAX_LEN = 20;
6
+ export const TAG_MAX_COUNT = 10;
7
+ /** '正面, 侧面' → ['正面', '侧面'](去空白/去空项/去重保序)。 */
8
+ export function parseTags(tagStr) {
9
+ const seen = new Set();
10
+ const out = [];
11
+ for (const t of String(tagStr ?? '').split(TAG_SEP)) {
12
+ const s = t.trim();
13
+ if (!s || seen.has(s))
14
+ continue;
15
+ seen.add(s);
16
+ out.push(s);
17
+ }
18
+ return out;
19
+ }
20
+ export function serializeTags(tags) {
21
+ return tags.join(TAG_SEP);
22
+ }
23
+ /** 硬规则:非空 + 单个 ≤20 + 数量 ≤10(非法即抛)。 */
24
+ export function validateTags(tags) {
25
+ if (tags.length === 0)
26
+ throw new FetchError('标签必填,当前是空列表');
27
+ for (const t of tags) {
28
+ if (t.length > TAG_MAX_LEN)
29
+ throw new FetchError('标签太长(' + t.length + ' > ' + TAG_MAX_LEN + '): ' + t);
30
+ }
31
+ if (tags.length > TAG_MAX_COUNT)
32
+ throw new FetchError('标签数量太多(' + tags.length + ' > ' + TAG_MAX_COUNT + ')');
33
+ return tags;
34
+ }
35
+ export function tagsContain(tagStr, tag) {
36
+ return parseTags(tagStr).includes(tag);
37
+ }
38
+ /** 照片目录解析:显式传参 > CALORIE_PHOTOS_DIR;缺失抛(不静默落盘)。 */
39
+ export function resolvePhotosDir(dir) {
40
+ const raw = dir ?? process.env.CALORIE_PHOTOS_DIR ?? '';
41
+ if (!raw)
42
+ throw new FetchError('照片目录未配置:请传参或设置 CALORIE_PHOTOS_DIR');
43
+ mkdirSync(raw, { recursive: true });
44
+ return resolve(raw);
45
+ }
46
+ const PHOTO_COLS = 'id, date, time, photo_path, tag, note, created_at';
47
+ function toRow(r) {
48
+ return { ...r, tag_list: parseTags(r.tag) };
49
+ }
50
+ export function getPhotoRow(db, id) {
51
+ const row = db.prepare('SELECT ' + PHOTO_COLS + ' FROM body_photos WHERE id = ?').get(id);
52
+ return row ? toRow(row) : null;
53
+ }
54
+ function todayISO() {
55
+ return new Date().toISOString().slice(0, 10);
56
+ }
57
+ function shiftISODate(iso, deltaDays) {
58
+ const t = Date.parse(iso + 'T12:00:00Z');
59
+ if (Number.isNaN(t))
60
+ throw new FetchError('日期非法: ' + iso);
61
+ return new Date(t + deltaDays * 86400000).toISOString().slice(0, 10);
62
+ }
63
+ export function listPhotos(db, filter = {}) {
64
+ const days = filter.days ?? 7;
65
+ const where = [];
66
+ const params = [];
67
+ if (filter.dateFrom) {
68
+ where.push('date >= ?');
69
+ params.push(filter.dateFrom);
70
+ }
71
+ if (filter.dateTo) {
72
+ where.push('date <= ?');
73
+ params.push(filter.dateTo);
74
+ }
75
+ if (!filter.dateFrom && !filter.dateTo) {
76
+ where.push('date >= ?');
77
+ params.push(shiftISODate(filter.today ?? todayISO(), -days));
78
+ }
79
+ const rows = db
80
+ .prepare('SELECT ' + PHOTO_COLS + ' FROM body_photos WHERE ' + where.join(' AND ') + ' ORDER BY date DESC, time DESC')
81
+ .all(...params);
82
+ let out = rows.map(toRow);
83
+ if (filter.tag)
84
+ out = out.filter((r) => tagsContain(r.tag, filter.tag));
85
+ const limit = filter.limit ?? 100;
86
+ if (limit)
87
+ out = out.slice(0, limit);
88
+ return out;
89
+ }
90
+ export function daysSinceTagPhoto(db, tag, beforeDate) {
91
+ const rows = db
92
+ .prepare('SELECT id, tag, date FROM body_photos WHERE date < ? ORDER BY date DESC, time DESC')
93
+ .all(beforeDate);
94
+ for (const r of rows) {
95
+ if (tagsContain(r.tag, tag)) {
96
+ const delta = Math.round((Date.parse(beforeDate + 'T12:00:00Z') - Date.parse(r.date + 'T12:00:00Z')) / 86400000);
97
+ return delta >= 0 ? delta : null;
98
+ }
99
+ }
100
+ return null;
101
+ }
102
+ /** 添加照片:文件复制进目录 + 落库(仅文件名入库)。不存在的源文件跳过。 */
103
+ export function addPhotos(db, photosDir, input) {
104
+ const tags = validateTags(parseTags(input.tag));
105
+ const serialized = serializeTags(tags);
106
+ const today = input.today ?? todayISO();
107
+ const now = input.nowTime ?? new Date().toTimeString().slice(0, 8);
108
+ const cnt = db.prepare('SELECT COUNT(*) AS n FROM body_photos WHERE date = ?').get(today);
109
+ const added = [];
110
+ let i = 0;
111
+ for (const srcPath of input.srcPaths) {
112
+ if (!existsSync(srcPath))
113
+ continue;
114
+ const ext = srcPath.slice(srcPath.lastIndexOf('.')).toLowerCase();
115
+ const destName = today + '_' + String(cnt.n + i + 1).padStart(3, '0') + ext;
116
+ cpSync(srcPath, join(photosDir, destName));
117
+ const run = db
118
+ .prepare('INSERT INTO body_photos (date, time, photo_path, tag, note) VALUES (?, ?, ?, ?, ?)')
119
+ .run(today, now, destName, serialized, input.note ?? '');
120
+ added.push({ id: Number(run.lastInsertRowid), file: destName });
121
+ i += 1;
122
+ }
123
+ return added;
124
+ }
125
+ export function deletePhoto(db, photosDir, id) {
126
+ const row = db.prepare('SELECT photo_path FROM body_photos WHERE id = ?').get(id);
127
+ if (!row)
128
+ return { deleted: false, fileDeleted: false };
129
+ db.prepare('DELETE FROM body_photos WHERE id = ?').run(id);
130
+ const file = join(photosDir, basename(row.photo_path));
131
+ if (existsSync(file)) {
132
+ rmSync(file);
133
+ return { deleted: true, fileDeleted: true };
134
+ }
135
+ return { deleted: true, fileDeleted: false };
136
+ }
137
+ export function updateTag(db, id, newTag) {
138
+ const row = db.prepare('SELECT id FROM body_photos WHERE id = ?').get(id);
139
+ if (!row)
140
+ return false;
141
+ const serialized = serializeTags(validateTags(parseTags(newTag)));
142
+ db.prepare('UPDATE body_photos SET tag = ? WHERE id = ?').run(serialized, id);
143
+ return true;
144
+ }
145
+ /** 追加标签(判重);返回新增标签数(不存在的照片回 0)。 */
146
+ export function tagAdd(db, id, tag) {
147
+ const photo = getPhotoRow(db, id);
148
+ if (!photo)
149
+ return 0;
150
+ const tags = validateTags(parseTags(tag));
151
+ const existing = [...photo.tag_list];
152
+ let added = 0;
153
+ for (const t of tags) {
154
+ if (existing.includes(t))
155
+ continue;
156
+ existing.push(t);
157
+ added += 1;
158
+ }
159
+ if (added === 0)
160
+ return 0;
161
+ db.prepare('UPDATE body_photos SET tag = ? WHERE id = ?').run(serializeTags(existing), id);
162
+ return added;
163
+ }
164
+ /** 移除单个标签(至少保留 1 个;一次只删 1 个)。 */
165
+ export function tagRemove(db, id, tag) {
166
+ const photo = getPhotoRow(db, id);
167
+ if (!photo)
168
+ return false;
169
+ const tags = parseTags(tag);
170
+ if (tags.length !== 1)
171
+ throw new FetchError('删标签一次只删 1 个,收到 ' + tags.length + ' 个');
172
+ const existing = [...photo.tag_list];
173
+ const rm = tags[0];
174
+ if (!existing.includes(rm))
175
+ return false;
176
+ if (existing.length <= 1)
177
+ throw new FetchError('每张照片至少保留 1 个标签');
178
+ db.prepare('UPDATE body_photos SET tag = ? WHERE id = ?').run(serializeTags(existing.filter((t) => t !== rm)), id);
179
+ return true;
180
+ }
181
+ /** gif 规划器:只出任务描述(起止、张数、标签),不跑图像处理、不碰二进制。 */
182
+ export function planGif(db, input) {
183
+ const photos = listPhotos(db, { tag: input.tag, dateFrom: input.dateFrom, dateTo: input.dateTo, days: input.days ?? 30, limit: null });
184
+ return {
185
+ task: 'generate_gif',
186
+ tag: input.tag,
187
+ dateFrom: photos.length > 0 ? photos[photos.length - 1].date : null,
188
+ dateTo: photos.length > 0 ? photos[0].date : null,
189
+ photoCount: photos.length,
190
+ photoIds: photos.map((p) => p.id),
191
+ };
192
+ }
193
+ //# sourceMappingURL=photos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"photos.js","sourceRoot":"","sources":["../../src/fetch/photos.ts"],"names":[],"mappings":"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"}