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.
- package/dist/analysis/anomaly/common.d.ts +53 -0
- package/dist/analysis/anomaly/common.d.ts.map +1 -0
- package/dist/analysis/anomaly/common.js +69 -0
- package/dist/analysis/anomaly/common.js.map +1 -0
- package/dist/analysis/anomaly/diet.d.ts +8 -0
- package/dist/analysis/anomaly/diet.d.ts.map +1 -0
- package/dist/analysis/anomaly/diet.js +95 -0
- package/dist/analysis/anomaly/diet.js.map +1 -0
- package/dist/analysis/anomaly/exercise.d.ts +9 -0
- package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
- package/dist/analysis/anomaly/exercise.js +116 -0
- package/dist/analysis/anomaly/exercise.js.map +1 -0
- package/dist/analysis/anomaly/index.d.ts +19 -0
- package/dist/analysis/anomaly/index.d.ts.map +1 -0
- package/dist/analysis/anomaly/index.js +51 -0
- package/dist/analysis/anomaly/index.js.map +1 -0
- package/dist/analysis/anomaly/overall.d.ts +13 -0
- package/dist/analysis/anomaly/overall.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall.js +128 -0
- package/dist/analysis/anomaly/overall.js.map +1 -0
- package/dist/analysis/anomaly/overall2.d.ts +5 -0
- package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall2.js +94 -0
- package/dist/analysis/anomaly/overall2.js.map +1 -0
- package/dist/analysis/anomaly/weight.d.ts +8 -0
- package/dist/analysis/anomaly/weight.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight.js +106 -0
- package/dist/analysis/anomaly/weight.js.map +1 -0
- package/dist/analysis/anomaly/weight2.d.ts +4 -0
- package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight2.js +59 -0
- package/dist/analysis/anomaly/weight2.js.map +1 -0
- package/dist/analysis/contraindications.d.ts +63 -0
- package/dist/analysis/contraindications.d.ts.map +1 -0
- package/dist/analysis/contraindications.js +121 -0
- package/dist/analysis/contraindications.js.map +1 -0
- package/dist/analysis/cross.d.ts +75 -0
- package/dist/analysis/cross.d.ts.map +1 -0
- package/dist/analysis/cross.js +283 -0
- package/dist/analysis/cross.js.map +1 -0
- package/dist/analysis/dashboard.d.ts +18 -0
- package/dist/analysis/dashboard.d.ts.map +1 -0
- package/dist/analysis/dashboard.js +48 -0
- package/dist/analysis/dashboard.js.map +1 -0
- package/dist/analysis/deficit.d.ts +44 -0
- package/dist/analysis/deficit.d.ts.map +1 -0
- package/dist/analysis/deficit.js +54 -0
- package/dist/analysis/deficit.js.map +1 -0
- package/dist/analysis/diet.d.ts +76 -0
- package/dist/analysis/diet.d.ts.map +1 -0
- package/dist/analysis/diet.js +164 -0
- package/dist/analysis/diet.js.map +1 -0
- package/dist/analysis/exercise.d.ts +98 -0
- package/dist/analysis/exercise.d.ts.map +1 -0
- package/dist/analysis/exercise.js +298 -0
- package/dist/analysis/exercise.js.map +1 -0
- package/dist/analysis/exerciseReview.d.ts +36 -0
- package/dist/analysis/exerciseReview.d.ts.map +1 -0
- package/dist/analysis/exerciseReview.js +50 -0
- package/dist/analysis/exerciseReview.js.map +1 -0
- package/dist/analysis/precision.d.ts +15 -0
- package/dist/analysis/precision.d.ts.map +1 -0
- package/dist/analysis/precision.js +38 -0
- package/dist/analysis/precision.js.map +1 -0
- package/dist/analysis/result.d.ts +15 -0
- package/dist/analysis/result.d.ts.map +1 -0
- package/dist/analysis/result.js +13 -0
- package/dist/analysis/result.js.map +1 -0
- package/dist/analysis/review.d.ts +118 -0
- package/dist/analysis/review.d.ts.map +1 -0
- package/dist/analysis/review.js +195 -0
- package/dist/analysis/review.js.map +1 -0
- package/dist/analysis/series.d.ts +42 -0
- package/dist/analysis/series.d.ts.map +1 -0
- package/dist/analysis/series.js +127 -0
- package/dist/analysis/series.js.map +1 -0
- package/dist/analysis/simulate.d.ts +43 -0
- package/dist/analysis/simulate.d.ts.map +1 -0
- package/dist/analysis/simulate.js +109 -0
- package/dist/analysis/simulate.js.map +1 -0
- package/dist/analysis/simulate2.d.ts +65 -0
- package/dist/analysis/simulate2.d.ts.map +1 -0
- package/dist/analysis/simulate2.js +173 -0
- package/dist/analysis/simulate2.js.map +1 -0
- package/dist/analysis/trend.d.ts +39 -0
- package/dist/analysis/trend.d.ts.map +1 -0
- package/dist/analysis/trend.js +48 -0
- package/dist/analysis/trend.js.map +1 -0
- package/dist/analysis/utils.d.ts +17 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +52 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/analysis/volatility.d.ts +43 -0
- package/dist/analysis/volatility.d.ts.map +1 -0
- package/dist/analysis/volatility.js +96 -0
- package/dist/analysis/volatility.js.map +1 -0
- package/dist/analysis/weight.d.ts +86 -0
- package/dist/analysis/weight.d.ts.map +1 -0
- package/dist/analysis/weight.js +219 -0
- package/dist/analysis/weight.js.map +1 -0
- package/dist/analysis/weightCompare.d.ts +63 -0
- package/dist/analysis/weightCompare.d.ts.map +1 -0
- package/dist/analysis/weightCompare.js +212 -0
- package/dist/analysis/weightCompare.js.map +1 -0
- package/dist/analysis/weightCompare2.d.ts +63 -0
- package/dist/analysis/weightCompare2.d.ts.map +1 -0
- package/dist/analysis/weightCompare2.js +211 -0
- package/dist/analysis/weightCompare2.js.map +1 -0
- package/dist/analysis/weightCompare3.d.ts +13 -0
- package/dist/analysis/weightCompare3.d.ts.map +1 -0
- package/dist/analysis/weightCompare3.js +199 -0
- package/dist/analysis/weightCompare3.js.map +1 -0
- package/dist/cli/cmd_read.d.ts +8 -0
- package/dist/cli/cmd_read.d.ts.map +1 -0
- package/dist/cli/cmd_read.js +719 -0
- package/dist/cli/cmd_read.js.map +1 -0
- package/dist/cli/keys.d.ts +333 -0
- package/dist/cli/keys.d.ts.map +1 -0
- package/dist/cli/keys.js +103 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/write.d.ts +24 -0
- package/dist/cli/write.d.ts.map +1 -0
- package/dist/cli/write.js +832 -0
- package/dist/cli/write.js.map +1 -0
- package/dist/fetch/audit.d.ts +25 -0
- package/dist/fetch/audit.d.ts.map +1 -0
- package/dist/fetch/audit.js +46 -0
- package/dist/fetch/audit.js.map +1 -0
- package/dist/fetch/batch.d.ts +68 -0
- package/dist/fetch/batch.d.ts.map +1 -0
- package/dist/fetch/batch.js +183 -0
- package/dist/fetch/batch.js.map +1 -0
- package/dist/fetch/body.d.ts +89 -0
- package/dist/fetch/body.d.ts.map +1 -0
- package/dist/fetch/body.js +217 -0
- package/dist/fetch/body.js.map +1 -0
- package/dist/fetch/cli.d.ts +3 -0
- package/dist/fetch/cli.d.ts.map +1 -0
- package/dist/fetch/cli.js +195 -0
- package/dist/fetch/cli.js.map +1 -0
- package/dist/fetch/cross-skill.d.ts +29 -0
- package/dist/fetch/cross-skill.d.ts.map +1 -0
- package/dist/fetch/cross-skill.js +42 -0
- package/dist/fetch/cross-skill.js.map +1 -0
- package/dist/fetch/db.d.ts +5 -0
- package/dist/fetch/db.d.ts.map +1 -0
- package/dist/fetch/db.js +4 -0
- package/dist/fetch/db.js.map +1 -0
- package/dist/fetch/diet.d.ts +174 -0
- package/dist/fetch/diet.d.ts.map +1 -0
- package/dist/fetch/diet.js +239 -0
- package/dist/fetch/diet.js.map +1 -0
- package/dist/fetch/errors.d.ts +5 -0
- package/dist/fetch/errors.d.ts.map +1 -0
- package/dist/fetch/errors.js +8 -0
- package/dist/fetch/errors.js.map +1 -0
- package/dist/fetch/exercise.d.ts +72 -0
- package/dist/fetch/exercise.d.ts.map +1 -0
- package/dist/fetch/exercise.js +270 -0
- package/dist/fetch/exercise.js.map +1 -0
- package/dist/fetch/goal.d.ts +48 -0
- package/dist/fetch/goal.d.ts.map +1 -0
- package/dist/fetch/goal.js +73 -0
- package/dist/fetch/goal.js.map +1 -0
- package/dist/fetch/goalHistory.d.ts +24 -0
- package/dist/fetch/goalHistory.d.ts.map +1 -0
- package/dist/fetch/goalHistory.js +51 -0
- package/dist/fetch/goalHistory.js.map +1 -0
- package/dist/fetch/history.d.ts +28 -0
- package/dist/fetch/history.d.ts.map +1 -0
- package/dist/fetch/history.js +29 -0
- package/dist/fetch/history.js.map +1 -0
- package/dist/fetch/index.d.ts +23 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +16 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/fetch/nutritionGoal.d.ts +115 -0
- package/dist/fetch/nutritionGoal.d.ts.map +1 -0
- package/dist/fetch/nutritionGoal.js +154 -0
- package/dist/fetch/nutritionGoal.js.map +1 -0
- package/dist/fetch/photos.d.ts +76 -0
- package/dist/fetch/photos.d.ts.map +1 -0
- package/dist/fetch/photos.js +193 -0
- package/dist/fetch/photos.js.map +1 -0
- package/dist/fetch/plan.d.ts +145 -0
- package/dist/fetch/plan.d.ts.map +1 -0
- package/dist/fetch/plan.js +258 -0
- package/dist/fetch/plan.js.map +1 -0
- package/dist/fetch/products.d.ts +62 -0
- package/dist/fetch/products.d.ts.map +1 -0
- package/dist/fetch/products.js +73 -0
- package/dist/fetch/products.js.map +1 -0
- package/dist/fetch/profile.d.ts +46 -0
- package/dist/fetch/profile.d.ts.map +1 -0
- package/dist/fetch/profile.js +105 -0
- package/dist/fetch/profile.js.map +1 -0
- package/dist/fetch/shapes.d.ts +41 -0
- package/dist/fetch/shapes.d.ts.map +1 -0
- package/dist/fetch/shapes.js +38 -0
- package/dist/fetch/shapes.js.map +1 -0
- package/dist/fetch/validate.d.ts +11 -0
- package/dist/fetch/validate.d.ts.map +1 -0
- package/dist/fetch/validate.js +64 -0
- package/dist/fetch/validate.js.map +1 -0
- package/dist/fetch/weight.d.ts +109 -0
- package/dist/fetch/weight.d.ts.map +1 -0
- package/dist/fetch/weight.js +210 -0
- package/dist/fetch/weight.js.map +1 -0
- package/dist/fetch/xunji-catalog.d.ts +17 -0
- package/dist/fetch/xunji-catalog.d.ts.map +1 -0
- package/dist/fetch/xunji-catalog.js +57 -0
- package/dist/fetch/xunji-catalog.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/kcal.d.ts +21 -0
- package/dist/kcal.d.ts.map +1 -0
- package/dist/kcal.js +27 -0
- package/dist/kcal.js.map +1 -0
- package/dist/migrate/migrate.d.ts +71 -0
- package/dist/migrate/migrate.d.ts.map +1 -0
- package/dist/migrate/migrate.js +450 -0
- package/dist/migrate/migrate.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +34 -0
- package/dist/paths.js.map +1 -0
- package/dist/render/analysisPlate.d.ts +49 -0
- package/dist/render/analysisPlate.d.ts.map +1 -0
- package/dist/render/analysisPlate.js +149 -0
- package/dist/render/analysisPlate.js.map +1 -0
- package/dist/render/bodyPlate.d.ts +55 -0
- package/dist/render/bodyPlate.d.ts.map +1 -0
- package/dist/render/bodyPlate.js +97 -0
- package/dist/render/bodyPlate.js.map +1 -0
- package/dist/render/diet.d.ts +47 -0
- package/dist/render/diet.d.ts.map +1 -0
- package/dist/render/diet.js +94 -0
- package/dist/render/diet.js.map +1 -0
- package/dist/render/envelope.d.ts +60 -0
- package/dist/render/envelope.d.ts.map +1 -0
- package/dist/render/envelope.js +111 -0
- package/dist/render/envelope.js.map +1 -0
- package/dist/render/errors.d.ts +10 -0
- package/dist/render/errors.d.ts.map +1 -0
- package/dist/render/errors.js +9 -0
- package/dist/render/errors.js.map +1 -0
- package/dist/render/exercise.d.ts +20 -0
- package/dist/render/exercise.d.ts.map +1 -0
- package/dist/render/exercise.js +32 -0
- package/dist/render/exercise.js.map +1 -0
- package/dist/render/goal.d.ts +24 -0
- package/dist/render/goal.d.ts.map +1 -0
- package/dist/render/goal.js +23 -0
- package/dist/render/goal.js.map +1 -0
- package/dist/render/goalExtra.d.ts +45 -0
- package/dist/render/goalExtra.d.ts.map +1 -0
- package/dist/render/goalExtra.js +94 -0
- package/dist/render/goalExtra.js.map +1 -0
- package/dist/render/goalPlate.d.ts +66 -0
- package/dist/render/goalPlate.d.ts.map +1 -0
- package/dist/render/goalPlate.js +110 -0
- package/dist/render/goalPlate.js.map +1 -0
- package/dist/render/health.d.ts +21 -0
- package/dist/render/health.d.ts.map +1 -0
- package/dist/render/health.js +41 -0
- package/dist/render/health.js.map +1 -0
- package/dist/render/help.d.ts +18 -0
- package/dist/render/help.d.ts.map +1 -0
- package/dist/render/help.js +58 -0
- package/dist/render/help.js.map +1 -0
- package/dist/render/home.d.ts +30 -0
- package/dist/render/home.d.ts.map +1 -0
- package/dist/render/home.js +73 -0
- package/dist/render/home.js.map +1 -0
- package/dist/render/html.d.ts +66 -0
- package/dist/render/html.d.ts.map +1 -0
- package/dist/render/html.js +510 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +26 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/insightPlate.d.ts +55 -0
- package/dist/render/insightPlate.d.ts.map +1 -0
- package/dist/render/insightPlate.js +97 -0
- package/dist/render/insightPlate.js.map +1 -0
- package/dist/render/library.d.ts +32 -0
- package/dist/render/library.d.ts.map +1 -0
- package/dist/render/library.js +54 -0
- package/dist/render/library.js.map +1 -0
- package/dist/render/photo.d.ts +101 -0
- package/dist/render/photo.d.ts.map +1 -0
- package/dist/render/photo.js +241 -0
- package/dist/render/photo.js.map +1 -0
- package/dist/render/planPlate.d.ts +40 -0
- package/dist/render/planPlate.d.ts.map +1 -0
- package/dist/render/planPlate.js +72 -0
- package/dist/render/planPlate.js.map +1 -0
- package/dist/render/profilePlate.d.ts +17 -0
- package/dist/render/profilePlate.d.ts.map +1 -0
- package/dist/render/profilePlate.js +18 -0
- package/dist/render/profilePlate.js.map +1 -0
- package/dist/render/ranking.d.ts +22 -0
- package/dist/render/ranking.d.ts.map +1 -0
- package/dist/render/ranking.js +63 -0
- package/dist/render/ranking.js.map +1 -0
- package/dist/render/receipt.d.ts +71 -0
- package/dist/render/receipt.d.ts.map +1 -0
- package/dist/render/receipt.js +65 -0
- package/dist/render/receipt.js.map +1 -0
- package/dist/render/weightPlate.d.ts +54 -0
- package/dist/render/weightPlate.d.ts.map +1 -0
- package/dist/render/weightPlate.js +110 -0
- package/dist/render/weightPlate.js.map +1 -0
- package/dist/schema.d.ts +25 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +281 -0
- package/dist/schema.js.map +1 -0
- package/dist/triggers/help-lookup.d.ts +28 -0
- package/dist/triggers/help-lookup.d.ts.map +1 -0
- package/dist/triggers/help-lookup.js +163 -0
- package/dist/triggers/help-lookup.js.map +1 -0
- package/dist/triggers/index.d.ts +24 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +78 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/scene-01-home.d.ts +4 -0
- package/dist/triggers/scene-01-home.d.ts.map +1 -0
- package/dist/triggers/scene-01-home.js +13 -0
- package/dist/triggers/scene-01-home.js.map +1 -0
- package/dist/triggers/scene-02-diet.d.ts +4 -0
- package/dist/triggers/scene-02-diet.d.ts.map +1 -0
- package/dist/triggers/scene-02-diet.js +74 -0
- package/dist/triggers/scene-02-diet.js.map +1 -0
- package/dist/triggers/scene-03-weight.d.ts +4 -0
- package/dist/triggers/scene-03-weight.d.ts.map +1 -0
- package/dist/triggers/scene-03-weight.js +62 -0
- package/dist/triggers/scene-03-weight.js.map +1 -0
- package/dist/triggers/scene-04-exercise.d.ts +4 -0
- package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
- package/dist/triggers/scene-04-exercise.js +43 -0
- package/dist/triggers/scene-04-exercise.js.map +1 -0
- package/dist/triggers/scene-05-workout.d.ts +4 -0
- package/dist/triggers/scene-05-workout.d.ts.map +1 -0
- package/dist/triggers/scene-05-workout.js +36 -0
- package/dist/triggers/scene-05-workout.js.map +1 -0
- package/dist/triggers/scene-06-goal.d.ts +4 -0
- package/dist/triggers/scene-06-goal.d.ts.map +1 -0
- package/dist/triggers/scene-06-goal.js +29 -0
- package/dist/triggers/scene-06-goal.js.map +1 -0
- package/dist/triggers/scene-07-profile.d.ts +4 -0
- package/dist/triggers/scene-07-profile.d.ts.map +1 -0
- package/dist/triggers/scene-07-profile.js +8 -0
- package/dist/triggers/scene-07-profile.js.map +1 -0
- package/dist/triggers/scene-08-body.d.ts +4 -0
- package/dist/triggers/scene-08-body.d.ts.map +1 -0
- package/dist/triggers/scene-08-body.js +17 -0
- package/dist/triggers/scene-08-body.js.map +1 -0
- package/dist/triggers/scene-09-photo.d.ts +4 -0
- package/dist/triggers/scene-09-photo.d.ts.map +1 -0
- package/dist/triggers/scene-09-photo.js +14 -0
- package/dist/triggers/scene-09-photo.js.map +1 -0
- package/dist/triggers/scene-10-analysis.d.ts +4 -0
- package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
- package/dist/triggers/scene-10-analysis.js +180 -0
- package/dist/triggers/scene-10-analysis.js.map +1 -0
- package/dist/triggers/types.d.ts +66 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +3 -0
- package/dist/triggers/types.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/** T12 #38 · 老库到新 schema 的一次性迁移(只读复制件 → 写新库)。
|
|
2
|
+
*
|
|
3
|
+
* 对照:
|
|
4
|
+
* - 老家 D:/2Study/StudyNotes/SKILLS/卡路里/scripts/db.py(只读对照,不跑不动 Python):
|
|
5
|
+
* 13 表 = 11 终态 + body_composition_new/_mig 历史重建临时表;entries→food_log 合并;
|
|
6
|
+
* sleep_records/fitness_goals 删除;intensity(中文低中高)→ difficulty 回填。
|
|
7
|
+
* - T1 #20 终态 schema(packages/skill-calorie/src/schema.ts TABLE_DDLS 11 表 +
|
|
8
|
+
* applyMigrations 收敛单线,口径以现行代码为准)。
|
|
9
|
+
* - 关键口径取数以现行代码为准:总热量排除饮水(analysis/series.ts WATER_NAME +
|
|
10
|
+
* fetch/diet.ts WATER_NAME,render/diet.ts 同口径);体重 COUNT+SUM(fetch/weight.ts
|
|
11
|
+
* weight_log);照片 COUNT(fetch/photos.ts body_photos)。
|
|
12
|
+
*
|
|
13
|
+
* 原则:
|
|
14
|
+
* - 只读 src(DatabaseSync readOnly 打开,从不对其 exec 写;前后 stat 大小/mtime 记入报告)。
|
|
15
|
+
* - 只写 dst(assertWritablePath 守卫:非 tmp 须 CALORIE_FORCE_PROD=1,真实 DB 零触碰)。
|
|
16
|
+
* - 幂等可重跑:dst 侧每表先 DELETE 再按“基表→_new→_mig→entries”确定序重插,id 尽量保留,
|
|
17
|
+
* 碰撞则顺序分配新 id(确定性),重跑结果一致。
|
|
18
|
+
* - 三代收敛宁可多记不可丢:body_photos/measurements/composition 的 _new/_mig 行全部收敛进终态表;
|
|
19
|
+
* 仅 workout_plans 受 UNIQUE(week,day,session) 约束去重(保留最小 id,冲突记入报告,回滚说明列出)。
|
|
20
|
+
* - 失败回滚:dst 写全程包在单个 IMMEDIATE 事务里(含复制 + applyMigrations 回填 + 对账),
|
|
21
|
+
* 对账不一致或任何异常即 ROLLBACK,dst 文件恢复到打开前状态(新文件则仅剩空 schema),见 MIGRATE_ROLLBACK.md。
|
|
22
|
+
* - 缺失阻断不返空:src 缺失/空库(11 表全无)、dst 不可写、行数/口径对不上,一律抛错不返空报告。
|
|
23
|
+
* - 面板/定时/外联动 out of scope:本模块只做表复制 + 对账,不碰任何渲染/定时/跨技能。
|
|
24
|
+
*/
|
|
25
|
+
import { mkdirSync, statSync } from 'node:fs';
|
|
26
|
+
import { dirname, resolve } from 'node:path';
|
|
27
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
28
|
+
import { applyMigrations, initDb, TABLE_DDLS } from '../schema.js';
|
|
29
|
+
import { assertWritablePath } from '../paths.js';
|
|
30
|
+
const WATER_NAME = '💧水';
|
|
31
|
+
export const FINAL_TABLES = Object.freeze(Object.keys(TABLE_DDLS));
|
|
32
|
+
/** 复制顺序:nutrition_products 先行(food_log 钠糖纤维回填依赖它),其余按终态表序。 */
|
|
33
|
+
const COPY_ORDER = Object.freeze([
|
|
34
|
+
'nutrition_products',
|
|
35
|
+
'food_log',
|
|
36
|
+
'daily_goal',
|
|
37
|
+
'exercise_log',
|
|
38
|
+
'weight_log',
|
|
39
|
+
'workout_plan_config',
|
|
40
|
+
'workout_plans',
|
|
41
|
+
'body_photos',
|
|
42
|
+
'user_profile',
|
|
43
|
+
'body_composition',
|
|
44
|
+
'body_measurements',
|
|
45
|
+
]);
|
|
46
|
+
const BODY_FAMILIES = new Set(['body_photos', 'body_measurements', 'body_composition']);
|
|
47
|
+
const LEGACY_SUFFIXES = ['_new', '_mig'];
|
|
48
|
+
/** food 另收 entries(老家 2026-07-12 改名残留,见 schema.ts M1)。 */
|
|
49
|
+
const FOOD_SOURCES = ['food_log', 'entries'];
|
|
50
|
+
export class MigrateMissingError extends Error {
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = 'MigrateMissingError';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class MigrateVerifyError extends Error {
|
|
57
|
+
report;
|
|
58
|
+
constructor(message, report) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'MigrateVerifyError';
|
|
61
|
+
this.report = report;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function assertNodeEngines() {
|
|
65
|
+
const parts = process.versions.node.split('.').map(Number);
|
|
66
|
+
const major = parts[0] ?? 0;
|
|
67
|
+
const minor = parts[1] ?? 0;
|
|
68
|
+
if (!(major > 22 || (major === 22 && minor >= 13))) {
|
|
69
|
+
throw new MigrateMissingError('node 低于 22.13:' + process.versions.node + '(铁律 engines>=22.13)');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function intensityToDifficulty(v) {
|
|
73
|
+
if (v === '低')
|
|
74
|
+
return 'easy';
|
|
75
|
+
if (v === '中')
|
|
76
|
+
return 'normal';
|
|
77
|
+
if (v === '高')
|
|
78
|
+
return 'hard';
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function listTables(db) {
|
|
82
|
+
const rows = db
|
|
83
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table'")
|
|
84
|
+
.all();
|
|
85
|
+
return new Set(rows.map((r) => r.name));
|
|
86
|
+
}
|
|
87
|
+
function tableCols(db, table) {
|
|
88
|
+
const rows = db.prepare('PRAGMA table_info(' + table + ')').all();
|
|
89
|
+
return rows.map((r) => r.name);
|
|
90
|
+
}
|
|
91
|
+
function countRows(db, table) {
|
|
92
|
+
const row = db.prepare('SELECT COUNT(*) AS n FROM ' + table).get();
|
|
93
|
+
return row.n;
|
|
94
|
+
}
|
|
95
|
+
function srcCandidates(table) {
|
|
96
|
+
// 通用收敛:任何终态表若残留 _new/_mig 同名表(一键回归/崩溃中断),一律收敛;
|
|
97
|
+
// food 另收 entries(老家改名残留)。BODY_FAMILIES 仅用于文档分组,逻辑全表通用。
|
|
98
|
+
void BODY_FAMILIES;
|
|
99
|
+
if (table === 'food_log')
|
|
100
|
+
return [...FOOD_SOURCES, ...LEGACY_SUFFIXES.map((s) => table + s)];
|
|
101
|
+
return [table, ...LEGACY_SUFFIXES.map((s) => table + s)];
|
|
102
|
+
}
|
|
103
|
+
function openSrcReadOnly(srcPath) {
|
|
104
|
+
try {
|
|
105
|
+
const db = new DatabaseSync(srcPath, { readOnly: true });
|
|
106
|
+
return { db, readOnly: true };
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// 极老 Node 无 readOnly 选项时降级:本模块仍只发 SELECT/PRAGMA,从不写 src。
|
|
110
|
+
const db = new DatabaseSync(srcPath);
|
|
111
|
+
return { db, readOnly: false };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function sumKcalExclWater(db, tables, candidates) {
|
|
115
|
+
const live = candidates.filter((t) => tables.has(t));
|
|
116
|
+
if (live.length === 0)
|
|
117
|
+
return 0;
|
|
118
|
+
const union = live.map((t) => 'SELECT calories, food_name FROM ' + t).join(' UNION ALL ');
|
|
119
|
+
const row = db
|
|
120
|
+
.prepare('SELECT COALESCE(SUM(calories),0) AS s FROM (' + union + ") WHERE food_name != '" + WATER_NAME + "'")
|
|
121
|
+
.get();
|
|
122
|
+
return row.s;
|
|
123
|
+
}
|
|
124
|
+
function sumWeight(db, tables) {
|
|
125
|
+
if (!tables.has('weight_log'))
|
|
126
|
+
return { n: 0, sum: 0 };
|
|
127
|
+
const row = db
|
|
128
|
+
.prepare('SELECT COUNT(*) AS n, COALESCE(SUM(weight_kg),0) AS s FROM weight_log')
|
|
129
|
+
.get();
|
|
130
|
+
return { n: row.n, sum: row.s };
|
|
131
|
+
}
|
|
132
|
+
function countPhotosConverged(db, tables) {
|
|
133
|
+
const live = srcCandidates('body_photos').filter((t) => tables.has(t));
|
|
134
|
+
if (live.length === 0)
|
|
135
|
+
return 0;
|
|
136
|
+
const union = live.map((t) => 'SELECT id FROM ' + t).join(' UNION ALL ');
|
|
137
|
+
const row = db.prepare('SELECT COUNT(*) AS n FROM (' + union + ')').get();
|
|
138
|
+
return row.n;
|
|
139
|
+
}
|
|
140
|
+
export function migrateCalorieDb(srcPath, dstPath, opts = {}) {
|
|
141
|
+
assertNodeEngines();
|
|
142
|
+
if (!srcPath)
|
|
143
|
+
throw new MigrateMissingError('缺 --src(老库复制件路径必填,不返空)');
|
|
144
|
+
if (!dstPath)
|
|
145
|
+
throw new MigrateMissingError('缺 --dst(新库路径必填,不返空)');
|
|
146
|
+
const srcAbs = resolve(srcPath);
|
|
147
|
+
const dstAbs = resolve(dstPath);
|
|
148
|
+
if (srcAbs === dstAbs)
|
|
149
|
+
throw new MigrateMissingError('src 与 dst 不能是同一文件(防覆盖老库复制件)');
|
|
150
|
+
let srcStat;
|
|
151
|
+
try {
|
|
152
|
+
const st = statSync(srcAbs);
|
|
153
|
+
if (!st.isFile())
|
|
154
|
+
throw new Error('非文件');
|
|
155
|
+
srcStat = { size: st.size, mtimeMs: st.mtimeMs };
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
throw new MigrateMissingError('src 不存在或不可读:' + srcAbs);
|
|
159
|
+
}
|
|
160
|
+
// dst 写守卫:非 tmp 须 CALORIE_FORCE_PROD=1(真实 DB 零触碰,见 paths.ts)。
|
|
161
|
+
assertWritablePath(dstAbs);
|
|
162
|
+
if (opts.allowOverwrite === false) {
|
|
163
|
+
try {
|
|
164
|
+
statSync(dstAbs);
|
|
165
|
+
throw new MigrateMissingError('dst 已存在且 allowOverwrite=false:' + dstAbs);
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
if (e instanceof MigrateMissingError)
|
|
169
|
+
throw e;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
mkdirSync(dirname(dstAbs), { recursive: true });
|
|
173
|
+
const { db: src, readOnly } = openSrcReadOnly(srcAbs);
|
|
174
|
+
try {
|
|
175
|
+
const srcTables = listTables(src);
|
|
176
|
+
const hasAnyFinal = [...FINAL_TABLES, 'entries'].some((t) => srcTables.has(t));
|
|
177
|
+
if (!hasAnyFinal) {
|
|
178
|
+
throw new MigrateMissingError('src 空库:11 终态表与 entries 全无(' + srcAbs + '),拒绝返空报告');
|
|
179
|
+
}
|
|
180
|
+
// 先收集 src 期望口径(事务外只读快照,用于事务内对账)。
|
|
181
|
+
const expectedCounts = new Map();
|
|
182
|
+
for (const table of COPY_ORDER) {
|
|
183
|
+
const raw = {};
|
|
184
|
+
const rows = [];
|
|
185
|
+
for (const cand of srcCandidates(table)) {
|
|
186
|
+
if (!srcTables.has(cand)) {
|
|
187
|
+
raw[cand] = 0;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const n = countRows(src, cand);
|
|
191
|
+
raw[cand] = n;
|
|
192
|
+
if (n === 0)
|
|
193
|
+
continue;
|
|
194
|
+
const got = src.prepare('SELECT * FROM ' + cand).all();
|
|
195
|
+
for (const r of got)
|
|
196
|
+
r.__srcTable = cand;
|
|
197
|
+
rows.push(...got);
|
|
198
|
+
}
|
|
199
|
+
expectedCounts.set(table, { raw, convergedRows: rows, converged: rows.length });
|
|
200
|
+
}
|
|
201
|
+
const srcKcal = sumKcalExclWater(src, srcTables, [...FOOD_SOURCES]);
|
|
202
|
+
const srcWeight = sumWeight(src, srcTables);
|
|
203
|
+
const srcPhotos = countPhotosConverged(src, srcTables);
|
|
204
|
+
const dst = new DatabaseSync(dstAbs);
|
|
205
|
+
try {
|
|
206
|
+
initDb(dst);
|
|
207
|
+
const dstTables = listTables(dst);
|
|
208
|
+
for (const t of COPY_ORDER) {
|
|
209
|
+
if (!dstTables.has(t))
|
|
210
|
+
throw new Error('dst 缺终态表:' + t);
|
|
211
|
+
}
|
|
212
|
+
const remapped = [];
|
|
213
|
+
const uniqueConflicts = [];
|
|
214
|
+
const warnings = [];
|
|
215
|
+
if (!readOnly)
|
|
216
|
+
warnings.push('src 未能以 readOnly 打开(Node 选项缺失),本脚本仍只发 SELECT/PRAGMA,未写 src;详见报告 srcReadOnly=false');
|
|
217
|
+
dst.exec('BEGIN IMMEDIATE');
|
|
218
|
+
try {
|
|
219
|
+
for (const table of COPY_ORDER) {
|
|
220
|
+
const dstCols = tableCols(dst, table);
|
|
221
|
+
const dstSet = new Set(dstCols);
|
|
222
|
+
dst.exec('DELETE FROM ' + table);
|
|
223
|
+
const bucket = expectedCounts.get(table);
|
|
224
|
+
const rows = bucket?.convergedRows ?? [];
|
|
225
|
+
if (rows.length === 0)
|
|
226
|
+
continue;
|
|
227
|
+
// 确定序:基表先、_new 次、_mig 末、entries 末;同表内按 id 升序(NULL 末)。
|
|
228
|
+
const orderOf = (cand) => {
|
|
229
|
+
if (cand === table)
|
|
230
|
+
return 0;
|
|
231
|
+
if (cand === table + '_new')
|
|
232
|
+
return 1;
|
|
233
|
+
if (cand === table + '_mig')
|
|
234
|
+
return 2;
|
|
235
|
+
return 3;
|
|
236
|
+
};
|
|
237
|
+
rows.sort((a, b) => {
|
|
238
|
+
const oa = orderOf(String(a.__srcTable));
|
|
239
|
+
const ob = orderOf(String(b.__srcTable));
|
|
240
|
+
if (oa !== ob)
|
|
241
|
+
return oa - ob;
|
|
242
|
+
const ia = typeof a.id === 'number' ? a.id : Number.MAX_SAFE_INTEGER;
|
|
243
|
+
const ib = typeof b.id === 'number' ? b.id : Number.MAX_SAFE_INTEGER;
|
|
244
|
+
return ia - ib;
|
|
245
|
+
});
|
|
246
|
+
const usedIds = new Set();
|
|
247
|
+
let maxId = 0;
|
|
248
|
+
for (const r of rows) {
|
|
249
|
+
if (typeof r.id === 'number' && Number.isInteger(r.id))
|
|
250
|
+
maxId = Math.max(maxId, r.id);
|
|
251
|
+
}
|
|
252
|
+
let nextId = maxId;
|
|
253
|
+
const usedUnique = new Set();
|
|
254
|
+
const srcColsPerTable = new Map();
|
|
255
|
+
for (const cand of srcCandidates(table)) {
|
|
256
|
+
if (!srcTables.has(cand))
|
|
257
|
+
continue;
|
|
258
|
+
srcColsPerTable.set(cand, new Set(tableCols(src, cand)));
|
|
259
|
+
}
|
|
260
|
+
for (const r of rows) {
|
|
261
|
+
const cand = String(r.__srcTable);
|
|
262
|
+
const srcSet = srcColsPerTable.get(cand) ?? new Set();
|
|
263
|
+
const cols = dstCols.filter((c) => srcSet.has(c) && c !== 'intensity' && r[c] !== undefined);
|
|
264
|
+
// exercise 特殊:intensity→difficulty 一次性回填(T1 M5 口径)。
|
|
265
|
+
const out = {};
|
|
266
|
+
for (const c of cols)
|
|
267
|
+
out[c] = r[c];
|
|
268
|
+
if (table === 'exercise_log' && dstSet.has('difficulty')) {
|
|
269
|
+
const hasDiff = srcSet.has('difficulty') ? r.difficulty : undefined;
|
|
270
|
+
if ((hasDiff === null || hasDiff === undefined) && srcSet.has('intensity')) {
|
|
271
|
+
const mapped = intensityToDifficulty(r.intensity);
|
|
272
|
+
if (mapped !== null)
|
|
273
|
+
out.difficulty = mapped;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// id 碰撞(跨世代同 id 不同行)→ 分配新 id,宁可多记不可丢。
|
|
277
|
+
if (out.id !== undefined && out.id !== null) {
|
|
278
|
+
const idNum = Number(out.id);
|
|
279
|
+
if (usedIds.has(idNum)) {
|
|
280
|
+
nextId += 1;
|
|
281
|
+
remapped.push({ table, fromTable: cand, oldId: idNum, newId: nextId });
|
|
282
|
+
out.id = nextId;
|
|
283
|
+
usedIds.add(nextId);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
usedIds.add(idNum);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// workout_plans 唯一键去重(保留最小 id,冲突记入报告)。
|
|
290
|
+
if (table === 'workout_plans') {
|
|
291
|
+
const key = String(out.week_number) + '|' + String(out.day_of_week) + '|' + String(out.session_index);
|
|
292
|
+
if (usedUnique.has(key)) {
|
|
293
|
+
uniqueConflicts.push({
|
|
294
|
+
table,
|
|
295
|
+
key,
|
|
296
|
+
keptId: Number.NaN,
|
|
297
|
+
droppedId: typeof out.id === 'number' ? out.id : -1,
|
|
298
|
+
fromTable: cand,
|
|
299
|
+
});
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
usedUnique.add(key);
|
|
303
|
+
}
|
|
304
|
+
const keys = Object.keys(out).filter((k) => k !== '__srcTable');
|
|
305
|
+
if (keys.length === 0)
|
|
306
|
+
continue;
|
|
307
|
+
const placeholders = keys.map(() => '?').join(', ');
|
|
308
|
+
const quoted = keys.map((k) => '"' + k + '"').join(', ');
|
|
309
|
+
const vals = keys.map((k) => out[k]);
|
|
310
|
+
dst.prepare('INSERT INTO ' + table + ' (' + quoted + ') VALUES (' + placeholders + ')').run(...vals);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// 复制后回填:钠糖纤维/目标列/废弃标记等(T1 applyMigrations 幂等语义)。
|
|
314
|
+
applyMigrations(dst);
|
|
315
|
+
// 事务内对账:行数 + 关键口径,不一致即回滚(零部分写入)。
|
|
316
|
+
const tables = [];
|
|
317
|
+
let allOk = true;
|
|
318
|
+
for (const table of COPY_ORDER) {
|
|
319
|
+
const bucket = expectedCounts.get(table);
|
|
320
|
+
const raw = bucket?.raw ?? {};
|
|
321
|
+
let expected = bucket?.converged ?? 0;
|
|
322
|
+
let skippedUnique = 0;
|
|
323
|
+
if (table === 'workout_plans') {
|
|
324
|
+
const seen = new Set();
|
|
325
|
+
let uniq = 0;
|
|
326
|
+
for (const r of bucket?.convergedRows ?? []) {
|
|
327
|
+
const key = String(r.week_number) + '|' + String(r.day_of_week) + '|' + String(r.session_index);
|
|
328
|
+
if (!seen.has(key)) {
|
|
329
|
+
seen.add(key);
|
|
330
|
+
uniq += 1;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
skippedUnique = expected - uniq;
|
|
334
|
+
expected = uniq;
|
|
335
|
+
}
|
|
336
|
+
const dstCount = countRows(dst, table);
|
|
337
|
+
const ok = dstCount === expected;
|
|
338
|
+
if (!ok)
|
|
339
|
+
allOk = false;
|
|
340
|
+
tables.push({ table, srcRaw: raw, srcConverged: expected, dst: dstCount, ok, skippedUnique });
|
|
341
|
+
}
|
|
342
|
+
const dstKcalRow = dst
|
|
343
|
+
.prepare("SELECT COALESCE(SUM(calories),0) AS s FROM food_log WHERE food_name != '" + WATER_NAME + "'")
|
|
344
|
+
.get();
|
|
345
|
+
const dstWeight = sumWeight(dst, listTables(dst));
|
|
346
|
+
const dstPhotosRow = dst.prepare('SELECT COUNT(*) AS n FROM body_photos').get();
|
|
347
|
+
// weight SUM 浮点:round2 后比对(kcal 公约:库里存原始,序列化前 round2)。
|
|
348
|
+
const wSrc = Math.round(srcWeight.sum * 100) / 100;
|
|
349
|
+
const wDst = Math.round(dstWeight.sum * 100) / 100;
|
|
350
|
+
const calibers = {
|
|
351
|
+
kcalExclWater: { label: '总热量(去水)', src: srcKcal, dst: dstKcalRow.s, ok: srcKcal === dstKcalRow.s },
|
|
352
|
+
weightCount: { label: '体重行数', src: srcWeight.n, dst: dstWeight.n, ok: srcWeight.n === dstWeight.n },
|
|
353
|
+
weightSum: { label: '体重合计kg(round2)', src: wSrc, dst: wDst, ok: wSrc === wDst },
|
|
354
|
+
photoCount: { label: '照片数', src: srcPhotos, dst: dstPhotosRow.n, ok: srcPhotos === dstPhotosRow.n },
|
|
355
|
+
};
|
|
356
|
+
if (!calibers.kcalExclWater.ok || !calibers.weightCount.ok || !calibers.weightSum.ok || !calibers.photoCount.ok) {
|
|
357
|
+
allOk = false;
|
|
358
|
+
}
|
|
359
|
+
const stAfter = statSync(srcAbs);
|
|
360
|
+
const report = {
|
|
361
|
+
src: srcAbs,
|
|
362
|
+
dst: dstAbs,
|
|
363
|
+
srcStatBefore: srcStat,
|
|
364
|
+
srcStatAfter: { size: stAfter.size, mtimeMs: stAfter.mtimeMs },
|
|
365
|
+
srcReadOnly: readOnly,
|
|
366
|
+
tables,
|
|
367
|
+
calibers,
|
|
368
|
+
remapped,
|
|
369
|
+
uniqueConflicts,
|
|
370
|
+
warnings,
|
|
371
|
+
ok: allOk,
|
|
372
|
+
};
|
|
373
|
+
if (!allOk) {
|
|
374
|
+
dst.exec('ROLLBACK');
|
|
375
|
+
throw new MigrateVerifyError('对账不一致已回滚(dst 恢复打开前状态),见报告 tables/calibers', report);
|
|
376
|
+
}
|
|
377
|
+
dst.exec('COMMIT');
|
|
378
|
+
const stAfterCommit = statSync(srcAbs);
|
|
379
|
+
report.srcStatAfter = { size: stAfterCommit.size, mtimeMs: stAfterCommit.mtimeMs };
|
|
380
|
+
if (report.srcStatBefore.size !== report.srcStatAfter.size || report.srcStatBefore.mtimeMs !== report.srcStatAfter.mtimeMs) {
|
|
381
|
+
report.warnings.push('src 文件 stat 在迁移前后发生变化(本脚本未写 src,请核查是否有外部进程触碰复制件)');
|
|
382
|
+
report.ok = false;
|
|
383
|
+
throw new MigrateVerifyError('src 复制件在迁移期间被外部改动,已提交但标为失败(dst 已写,src 需重取复制件后重跑)', report);
|
|
384
|
+
}
|
|
385
|
+
return report;
|
|
386
|
+
}
|
|
387
|
+
catch (e) {
|
|
388
|
+
try {
|
|
389
|
+
dst.exec('ROLLBACK');
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
// 已回滚或无事务:忽略二次错误,抛原始错误。
|
|
393
|
+
}
|
|
394
|
+
throw e;
|
|
395
|
+
}
|
|
396
|
+
finally {
|
|
397
|
+
dst.close();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
finally {
|
|
401
|
+
src.close();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
catch (e) {
|
|
405
|
+
try {
|
|
406
|
+
src.close();
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
// 忽略关闭错误。
|
|
410
|
+
}
|
|
411
|
+
throw e;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/** 报告渲染:人读对账表(一行一表 + 口径抽查)。 */
|
|
415
|
+
export function formatReportText(report) {
|
|
416
|
+
const lines = [];
|
|
417
|
+
lines.push('src: ' + report.src + ' (readOnly=' + String(report.srcReadOnly) + ')');
|
|
418
|
+
lines.push('dst: ' + report.dst);
|
|
419
|
+
lines.push('表 行数对账(src收敛 → dst):');
|
|
420
|
+
for (const t of report.tables) {
|
|
421
|
+
const raw = Object.entries(t.srcRaw)
|
|
422
|
+
.map(([k, v]) => k + '=' + String(v))
|
|
423
|
+
.join(' ');
|
|
424
|
+
lines.push(' ' + t.table + ': ' + raw + ' => ' + String(t.srcConverged) + ' → ' + String(t.dst) + ' ' + (t.ok ? 'OK' : 'MISMATCH') +
|
|
425
|
+
(t.skippedUnique ? ' (UNIQUE去重' + String(t.skippedUnique) + ')' : ''));
|
|
426
|
+
}
|
|
427
|
+
lines.push('口径抽查(现行代码口径):');
|
|
428
|
+
for (const c of [report.calibers.kcalExclWater, report.calibers.weightCount, report.calibers.weightSum, report.calibers.photoCount]) {
|
|
429
|
+
lines.push(' ' + c.label + ': src=' + String(c.src) + ' dst=' + String(c.dst) + ' ' + (c.ok ? 'OK' : 'MISMATCH'));
|
|
430
|
+
}
|
|
431
|
+
if (report.remapped.length > 0) {
|
|
432
|
+
lines.push('跨世代同 id 重映射(多记不丢)' + String(report.remapped.length) + ' 行:');
|
|
433
|
+
for (const r of report.remapped.slice(0, 20)) {
|
|
434
|
+
lines.push(' ' + r.table + ' ' + r.fromTable + ' id ' + String(r.oldId) + ' → ' + String(r.newId));
|
|
435
|
+
}
|
|
436
|
+
if (report.remapped.length > 20)
|
|
437
|
+
lines.push(' …另 ' + String(report.remapped.length - 20) + ' 行略');
|
|
438
|
+
}
|
|
439
|
+
if (report.uniqueConflicts.length > 0) {
|
|
440
|
+
lines.push('UNIQUE 冲突去重(workout_plans 保留最小 id)' + String(report.uniqueConflicts.length) + ' 行,见回滚说明:');
|
|
441
|
+
for (const u of report.uniqueConflicts.slice(0, 20)) {
|
|
442
|
+
lines.push(' key ' + u.key + ' drop id ' + String(u.droppedId) + ' from ' + u.fromTable);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
for (const w of report.warnings)
|
|
446
|
+
lines.push('WARN: ' + w);
|
|
447
|
+
lines.push(report.ok ? 'MIGRATE OK(幂等可重跑:同 src/dst 重跑行数一致)' : 'MIGRATE FAIL(已回滚,见 MIGRATE_ROLLBACK.md)');
|
|
448
|
+
return lines.join('\n');
|
|
449
|
+
}
|
|
450
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/migrate/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const DB_FILENAME = "calorie_data.db";
|
|
2
|
+
export declare function resolveDbDir(): string;
|
|
3
|
+
export declare function resolveDbPath(filename?: string, dir?: string): string;
|
|
4
|
+
/** 测试隔离守卫:非 tmp 路径写库须 CALORIE_FORCE_PROD=1(老家哨兵语义的 TS 版)。 */
|
|
5
|
+
export declare function assertWritablePath(dbPath: string): void;
|
|
6
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAE7C,wBAAgB,YAAY,IAAI,MAAM,CASrC;AAED,wBAAgB,aAAa,CAAC,QAAQ,SAAc,EAAE,GAAG,SAAiB,GAAG,MAAM,CAGlF;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAYvD"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** T1 #20 · DB 路径解析与隔离守卫(对照老家 db.find_db_path + cwd 哨兵)。
|
|
2
|
+
*
|
|
3
|
+
* 与老家的一处有意偏离:老家缺 SKILLS_DB_PATH 时静默落 D:/.db;TS 线按铁律
|
|
4
|
+
* 「缺失阻断不返空」直接抛错,拒绝隐式写生产。测试一律传显式 tmp 路径。
|
|
5
|
+
*/
|
|
6
|
+
import { mkdirSync } from 'node:fs';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
8
|
+
import { join, resolve } from 'node:path';
|
|
9
|
+
export const DB_FILENAME = 'calorie_data.db';
|
|
10
|
+
export function resolveDbDir() {
|
|
11
|
+
const env = process.env.SKILLS_DB_PATH;
|
|
12
|
+
if (!env) {
|
|
13
|
+
throw new Error('[skill-calorie] SKILLS_DB_PATH 未设置:拒绝隐式落盘。' +
|
|
14
|
+
'生产请设置 SKILLS_DB_PATH;测试请传显式 tmp 路径。');
|
|
15
|
+
}
|
|
16
|
+
return env;
|
|
17
|
+
}
|
|
18
|
+
export function resolveDbPath(filename = DB_FILENAME, dir = resolveDbDir()) {
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
return join(dir, filename);
|
|
21
|
+
}
|
|
22
|
+
/** 测试隔离守卫:非 tmp 路径写库须 CALORIE_FORCE_PROD=1(老家哨兵语义的 TS 版)。 */
|
|
23
|
+
export function assertWritablePath(dbPath) {
|
|
24
|
+
const forceProd = process.env.CALORIE_FORCE_PROD === '1';
|
|
25
|
+
const underTmp = resolve(dbPath).startsWith(resolve(tmpdir()));
|
|
26
|
+
if (!underTmp && !forceProd) {
|
|
27
|
+
throw new Error(`[skill-calorie] 拒绝写入非 tmp 路径 ${dbPath}:测试隔离守卫。` +
|
|
28
|
+
'如确需生产写,请设置 CALORIE_FORCE_PROD=1(opt-in 可见)。');
|
|
29
|
+
}
|
|
30
|
+
if (!underTmp && forceProd) {
|
|
31
|
+
console.error(`[skill-calorie] CALORIE_FORCE_PROD=1: 写入 ${dbPath}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAE7C,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,4CAA4C;YAC1C,qCAAqC,CACxC,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAQ,GAAG,WAAW,EAAE,GAAG,GAAG,YAAY,EAAE;IACxE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,GAAG,CAAC;IACzD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,UAAU;YAC9C,6CAA6C,CAChD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,4CAA4C,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** T9 #28 · 分析盘数据(render_analysis 对应:combined/deficit/diet_review)。
|
|
2
|
+
*
|
|
3
|
+
* 死规矩:数列唯一源 T5 buildSeries(resolveWindow 解析窗口别名,不自造日期偏移);
|
|
4
|
+
* 组合相关走 analyzePair(11 配对原样,pair 非法即 bad-input);缺口/趋势为 T7 薄壳
|
|
5
|
+
* (buildDeficitData/buildTrendData,不自算);饮食复盘三件套为 T5 口径
|
|
6
|
+
* (dietCalorieTrend/dietMacroRatio/dietDeficitAnalysis,rejection 即阻断)。
|
|
7
|
+
* 餐别窗口跟 diet.ts:复盘附带按餐桶汇总,归类走 inferMealType(与 MEAL_WINDOWS
|
|
8
|
+
* 同源),加餐 = 下午茶 + 夜宵;窗口存在性先断言(老家旧口径作废)。
|
|
9
|
+
*/
|
|
10
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
11
|
+
import type { DaySeries } from '../analysis/series.js';
|
|
12
|
+
import type { PairAnalysis } from '../analysis/cross.js';
|
|
13
|
+
import type { DeficitData } from '../analysis/deficit.js';
|
|
14
|
+
import type { TrendData } from '../analysis/trend.js';
|
|
15
|
+
import type { CalorieTrend, DeficitAnalysis, MacroRatio } from '../analysis/diet.js';
|
|
16
|
+
import type { AnalysisResult } from '../analysis/result.js';
|
|
17
|
+
import type { MealBucket } from './diet.js';
|
|
18
|
+
export declare const COMBINED_PAIRS: string[];
|
|
19
|
+
export interface CombinedAnalysis {
|
|
20
|
+
pair: string;
|
|
21
|
+
window: string;
|
|
22
|
+
start: string;
|
|
23
|
+
end: string;
|
|
24
|
+
series: DaySeries[];
|
|
25
|
+
analysis: PairAnalysis;
|
|
26
|
+
}
|
|
27
|
+
/** 组合分析盘(combined_analysis):pair + 窗口别名,series→analyzePair 直通。 */
|
|
28
|
+
export declare function buildCombinedAnalysis(db: DatabaseSync, pair: string, window?: string, start?: string | null, end?: string | null, today?: string): CombinedAnalysis;
|
|
29
|
+
/** 缺口盘(calorie_deficit):T7 薄壳直通,空窗转 missing-data。 */
|
|
30
|
+
export declare function buildDeficitPlate(db: DatabaseSync, start: string, end: string): DeficitData;
|
|
31
|
+
/** 趋势盘(render_analysis 趋势段):T7 薄壳直通。 */
|
|
32
|
+
export declare function buildTrendPlate(db: DatabaseSync, start: string, end: string): TrendData;
|
|
33
|
+
export interface ReviewMealSlice {
|
|
34
|
+
meal: MealBucket;
|
|
35
|
+
days: number;
|
|
36
|
+
totalCalories: number;
|
|
37
|
+
}
|
|
38
|
+
export interface DietReview {
|
|
39
|
+
start: string;
|
|
40
|
+
end: string;
|
|
41
|
+
trend: AnalysisResult<CalorieTrend>;
|
|
42
|
+
macro: AnalysisResult<MacroRatio>;
|
|
43
|
+
deficit: AnalysisResult<DeficitAnalysis>;
|
|
44
|
+
loggedDays: number;
|
|
45
|
+
byMeal: ReviewMealSlice[];
|
|
46
|
+
}
|
|
47
|
+
/** 饮食复盘盘(diet_review/nutrition_ratio):T5 三件套 + 按餐桶汇总(MEAL_WINDOWS 同源)。 */
|
|
48
|
+
export declare function buildDietReview(db: DatabaseSync, start: string, end: string): DietReview;
|
|
49
|
+
//# sourceMappingURL=analysisPlate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysisPlate.d.ts","sourceRoot":"","sources":["../../src/render/analysisPlate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,eAAO,MAAM,cAAc,UAAqB,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAQD,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,SAAQ,EACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,gBAAgB,CAgClB;AAED,qDAAqD;AACrD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAU3F;AAED,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAUvF;AAgBD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IACpC,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAClC,OAAO,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAuCxF"}
|