trainbud 0.5.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 (274) hide show
  1. package/.env.example +11 -0
  2. package/CHANGELOG.md +675 -0
  3. package/LICENSE +21 -0
  4. package/QUICKSTART.md +182 -0
  5. package/README.md +322 -0
  6. package/dist/appDb.d.ts +83 -0
  7. package/dist/appDb.d.ts.map +1 -0
  8. package/dist/appDb.js +239 -0
  9. package/dist/appDb.js.map +1 -0
  10. package/dist/check.d.ts +12 -0
  11. package/dist/check.d.ts.map +1 -0
  12. package/dist/check.js +230 -0
  13. package/dist/check.js.map +1 -0
  14. package/dist/cli.d.ts +3 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +457 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/config.d.ts +61 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +241 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/dashboard.d.ts +8 -0
  23. package/dist/dashboard.d.ts.map +1 -0
  24. package/dist/dashboard.js +1004 -0
  25. package/dist/dashboard.js.map +1 -0
  26. package/dist/dashboardCharts.d.ts +99 -0
  27. package/dist/dashboardCharts.d.ts.map +1 -0
  28. package/dist/dashboardCharts.js +317 -0
  29. package/dist/dashboardCharts.js.map +1 -0
  30. package/dist/dashboardData.d.ts +89 -0
  31. package/dist/dashboardData.d.ts.map +1 -0
  32. package/dist/dashboardData.js +228 -0
  33. package/dist/dashboardData.js.map +1 -0
  34. package/dist/detect/baseline.d.ts +17 -0
  35. package/dist/detect/baseline.d.ts.map +1 -0
  36. package/dist/detect/baseline.js +62 -0
  37. package/dist/detect/baseline.js.map +1 -0
  38. package/dist/detect/countdown.d.ts +30 -0
  39. package/dist/detect/countdown.d.ts.map +1 -0
  40. package/dist/detect/countdown.js +79 -0
  41. package/dist/detect/countdown.js.map +1 -0
  42. package/dist/detect/detectors.d.ts +20 -0
  43. package/dist/detect/detectors.d.ts.map +1 -0
  44. package/dist/detect/detectors.js +291 -0
  45. package/dist/detect/detectors.js.map +1 -0
  46. package/dist/detect/findings.d.ts +29 -0
  47. package/dist/detect/findings.d.ts.map +1 -0
  48. package/dist/detect/findings.js +2 -0
  49. package/dist/detect/findings.js.map +1 -0
  50. package/dist/detect/forecast.d.ts +33 -0
  51. package/dist/detect/forecast.d.ts.map +1 -0
  52. package/dist/detect/forecast.js +122 -0
  53. package/dist/detect/forecast.js.map +1 -0
  54. package/dist/detect/index.d.ts +50 -0
  55. package/dist/detect/index.d.ts.map +1 -0
  56. package/dist/detect/index.js +114 -0
  57. package/dist/detect/index.js.map +1 -0
  58. package/dist/detect/sleepQuality.d.ts +21 -0
  59. package/dist/detect/sleepQuality.d.ts.map +1 -0
  60. package/dist/detect/sleepQuality.js +164 -0
  61. package/dist/detect/sleepQuality.js.map +1 -0
  62. package/dist/detect/trimp.d.ts +22 -0
  63. package/dist/detect/trimp.d.ts.map +1 -0
  64. package/dist/detect/trimp.js +77 -0
  65. package/dist/detect/trimp.js.map +1 -0
  66. package/dist/detect/week.d.ts +31 -0
  67. package/dist/detect/week.d.ts.map +1 -0
  68. package/dist/detect/week.js +184 -0
  69. package/dist/detect/week.js.map +1 -0
  70. package/dist/garmin/auth.d.ts +10 -0
  71. package/dist/garmin/auth.d.ts.map +1 -0
  72. package/dist/garmin/auth.js +81 -0
  73. package/dist/garmin/auth.js.map +1 -0
  74. package/dist/garmin/cache.d.ts +42 -0
  75. package/dist/garmin/cache.d.ts.map +1 -0
  76. package/dist/garmin/cache.js +141 -0
  77. package/dist/garmin/cache.js.map +1 -0
  78. package/dist/garmin/client.d.ts +22 -0
  79. package/dist/garmin/client.d.ts.map +1 -0
  80. package/dist/garmin/client.js +237 -0
  81. package/dist/garmin/client.js.map +1 -0
  82. package/dist/garmin/daily.d.ts +24 -0
  83. package/dist/garmin/daily.d.ts.map +1 -0
  84. package/dist/garmin/daily.js +96 -0
  85. package/dist/garmin/daily.js.map +1 -0
  86. package/dist/garmin/garminApiTypes.d.ts +70 -0
  87. package/dist/garmin/garminApiTypes.d.ts.map +1 -0
  88. package/dist/garmin/garminApiTypes.js +3 -0
  89. package/dist/garmin/garminApiTypes.js.map +1 -0
  90. package/dist/garmin/garminConnect.d.ts +17 -0
  91. package/dist/garmin/garminConnect.d.ts.map +1 -0
  92. package/dist/garmin/garminConnect.js +5 -0
  93. package/dist/garmin/garminConnect.js.map +1 -0
  94. package/dist/garmin/partial.d.ts +32 -0
  95. package/dist/garmin/partial.d.ts.map +1 -0
  96. package/dist/garmin/partial.js +38 -0
  97. package/dist/garmin/partial.js.map +1 -0
  98. package/dist/garmin/rawApi.d.ts +59 -0
  99. package/dist/garmin/rawApi.d.ts.map +1 -0
  100. package/dist/garmin/rawApi.js +113 -0
  101. package/dist/garmin/rawApi.js.map +1 -0
  102. package/dist/garmin/types.d.ts +85 -0
  103. package/dist/garmin/types.d.ts.map +1 -0
  104. package/dist/garmin/types.js +11 -0
  105. package/dist/garmin/types.js.map +1 -0
  106. package/dist/history/capture.d.ts +12 -0
  107. package/dist/history/capture.d.ts.map +1 -0
  108. package/dist/history/capture.js +63 -0
  109. package/dist/history/capture.js.map +1 -0
  110. package/dist/history/context.d.ts +51 -0
  111. package/dist/history/context.d.ts.map +1 -0
  112. package/dist/history/context.js +122 -0
  113. package/dist/history/context.js.map +1 -0
  114. package/dist/history/fallback.d.ts +72 -0
  115. package/dist/history/fallback.d.ts.map +1 -0
  116. package/dist/history/fallback.js +185 -0
  117. package/dist/history/fallback.js.map +1 -0
  118. package/dist/history/ingest.d.ts +44 -0
  119. package/dist/history/ingest.d.ts.map +1 -0
  120. package/dist/history/ingest.js +347 -0
  121. package/dist/history/ingest.js.map +1 -0
  122. package/dist/history/scheduler.d.ts +20 -0
  123. package/dist/history/scheduler.d.ts.map +1 -0
  124. package/dist/history/scheduler.js +54 -0
  125. package/dist/history/scheduler.js.map +1 -0
  126. package/dist/history/schema.d.ts +41 -0
  127. package/dist/history/schema.d.ts.map +1 -0
  128. package/dist/history/schema.js +91 -0
  129. package/dist/history/schema.js.map +1 -0
  130. package/dist/history/store.d.ts +112 -0
  131. package/dist/history/store.d.ts.map +1 -0
  132. package/dist/history/store.js +282 -0
  133. package/dist/history/store.js.map +1 -0
  134. package/dist/httpServer.d.ts +55 -0
  135. package/dist/httpServer.d.ts.map +1 -0
  136. package/dist/httpServer.js +1027 -0
  137. package/dist/httpServer.js.map +1 -0
  138. package/dist/index.d.ts +3 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +11 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/mcpConfig.d.ts +56 -0
  143. package/dist/mcpConfig.d.ts.map +1 -0
  144. package/dist/mcpConfig.js +106 -0
  145. package/dist/mcpConfig.js.map +1 -0
  146. package/dist/pairApi.d.ts +14 -0
  147. package/dist/pairApi.d.ts.map +1 -0
  148. package/dist/pairApi.js +38 -0
  149. package/dist/pairApi.js.map +1 -0
  150. package/dist/paths.d.ts +45 -0
  151. package/dist/paths.d.ts.map +1 -0
  152. package/dist/paths.js +105 -0
  153. package/dist/paths.js.map +1 -0
  154. package/dist/profile.d.ts +123 -0
  155. package/dist/profile.d.ts.map +1 -0
  156. package/dist/profile.js +327 -0
  157. package/dist/profile.js.map +1 -0
  158. package/dist/promptApi.d.ts +43 -0
  159. package/dist/promptApi.d.ts.map +1 -0
  160. package/dist/promptApi.js +328 -0
  161. package/dist/promptApi.js.map +1 -0
  162. package/dist/promptSuggestions.d.ts +16 -0
  163. package/dist/promptSuggestions.d.ts.map +1 -0
  164. package/dist/promptSuggestions.js +141 -0
  165. package/dist/promptSuggestions.js.map +1 -0
  166. package/dist/selfTest.d.ts +53 -0
  167. package/dist/selfTest.d.ts.map +1 -0
  168. package/dist/selfTest.js +225 -0
  169. package/dist/selfTest.js.map +1 -0
  170. package/dist/server.d.ts +10 -0
  171. package/dist/server.d.ts.map +1 -0
  172. package/dist/server.js +67 -0
  173. package/dist/server.js.map +1 -0
  174. package/dist/setup.d.ts +2 -0
  175. package/dist/setup.d.ts.map +1 -0
  176. package/dist/setup.js +210 -0
  177. package/dist/setup.js.map +1 -0
  178. package/dist/toolErrors.d.ts +2 -0
  179. package/dist/toolErrors.d.ts.map +1 -0
  180. package/dist/toolErrors.js +18 -0
  181. package/dist/toolErrors.js.map +1 -0
  182. package/dist/tools/activities.d.ts +18 -0
  183. package/dist/tools/activities.d.ts.map +1 -0
  184. package/dist/tools/activities.js +182 -0
  185. package/dist/tools/activities.js.map +1 -0
  186. package/dist/tools/bodyComposition.d.ts +10 -0
  187. package/dist/tools/bodyComposition.d.ts.map +1 -0
  188. package/dist/tools/bodyComposition.js +139 -0
  189. package/dist/tools/bodyComposition.js.map +1 -0
  190. package/dist/tools/context.d.ts +8 -0
  191. package/dist/tools/context.d.ts.map +1 -0
  192. package/dist/tools/context.js +148 -0
  193. package/dist/tools/context.js.map +1 -0
  194. package/dist/tools/findings.d.ts +7 -0
  195. package/dist/tools/findings.d.ts.map +1 -0
  196. package/dist/tools/findings.js +51 -0
  197. package/dist/tools/findings.js.map +1 -0
  198. package/dist/tools/heartRate.d.ts +10 -0
  199. package/dist/tools/heartRate.d.ts.map +1 -0
  200. package/dist/tools/heartRate.js +105 -0
  201. package/dist/tools/heartRate.js.map +1 -0
  202. package/dist/tools/index.d.ts +66 -0
  203. package/dist/tools/index.d.ts.map +1 -0
  204. package/dist/tools/index.js +101 -0
  205. package/dist/tools/index.js.map +1 -0
  206. package/dist/tools/payloads.d.ts +148 -0
  207. package/dist/tools/payloads.d.ts.map +1 -0
  208. package/dist/tools/payloads.js +2 -0
  209. package/dist/tools/payloads.js.map +1 -0
  210. package/dist/tools/recovery.d.ts +31 -0
  211. package/dist/tools/recovery.d.ts.map +1 -0
  212. package/dist/tools/recovery.js +350 -0
  213. package/dist/tools/recovery.js.map +1 -0
  214. package/dist/tools/sleep.d.ts +10 -0
  215. package/dist/tools/sleep.d.ts.map +1 -0
  216. package/dist/tools/sleep.js +124 -0
  217. package/dist/tools/sleep.js.map +1 -0
  218. package/dist/tools/stress.d.ts +11 -0
  219. package/dist/tools/stress.d.ts.map +1 -0
  220. package/dist/tools/stress.js +108 -0
  221. package/dist/tools/stress.js.map +1 -0
  222. package/dist/tools/trainingInsights.d.ts +15 -0
  223. package/dist/tools/trainingInsights.d.ts.map +1 -0
  224. package/dist/tools/trainingInsights.js +79 -0
  225. package/dist/tools/trainingInsights.js.map +1 -0
  226. package/dist/tools/types.d.ts +12 -0
  227. package/dist/tools/types.d.ts.map +1 -0
  228. package/dist/tools/types.js +2 -0
  229. package/dist/tools/types.js.map +1 -0
  230. package/dist/tools/vo2Max.d.ts +11 -0
  231. package/dist/tools/vo2Max.d.ts.map +1 -0
  232. package/dist/tools/vo2Max.js +110 -0
  233. package/dist/tools/vo2Max.js.map +1 -0
  234. package/dist/tools/week.d.ts +12 -0
  235. package/dist/tools/week.d.ts.map +1 -0
  236. package/dist/tools/week.js +74 -0
  237. package/dist/tools/week.js.map +1 -0
  238. package/dist/usage.d.ts +104 -0
  239. package/dist/usage.d.ts.map +1 -0
  240. package/dist/usage.js +247 -0
  241. package/dist/usage.js.map +1 -0
  242. package/dist/utils/batch.d.ts +2 -0
  243. package/dist/utils/batch.d.ts.map +1 -0
  244. package/dist/utils/batch.js +18 -0
  245. package/dist/utils/batch.js.map +1 -0
  246. package/dist/utils/helpers.d.ts +32 -0
  247. package/dist/utils/helpers.d.ts.map +1 -0
  248. package/dist/utils/helpers.js +188 -0
  249. package/dist/utils/helpers.js.map +1 -0
  250. package/dist/utils/jsonFile.d.ts +19 -0
  251. package/dist/utils/jsonFile.d.ts.map +1 -0
  252. package/dist/utils/jsonFile.js +24 -0
  253. package/dist/utils/jsonFile.js.map +1 -0
  254. package/dist/utils/logger.d.ts +4 -0
  255. package/dist/utils/logger.d.ts.map +1 -0
  256. package/dist/utils/logger.js +97 -0
  257. package/dist/utils/logger.js.map +1 -0
  258. package/dist/utils/secretFile.d.ts +15 -0
  259. package/dist/utils/secretFile.d.ts.map +1 -0
  260. package/dist/utils/secretFile.js +47 -0
  261. package/dist/utils/secretFile.js.map +1 -0
  262. package/dist/utils/stdio.d.ts +10 -0
  263. package/dist/utils/stdio.d.ts.map +1 -0
  264. package/dist/utils/stdio.js +70 -0
  265. package/dist/utils/stdio.js.map +1 -0
  266. package/dist/version.d.ts +2 -0
  267. package/dist/version.d.ts.map +1 -0
  268. package/dist/version.js +7 -0
  269. package/dist/version.js.map +1 -0
  270. package/dist/watchApi.d.ts +264 -0
  271. package/dist/watchApi.d.ts.map +1 -0
  272. package/dist/watchApi.js +333 -0
  273. package/dist/watchApi.js.map +1 -0
  274. package/package.json +77 -0
package/dist/config.js ADDED
@@ -0,0 +1,241 @@
1
+ import { config as loadEnv } from "dotenv";
2
+ import { randomBytes } from "node:crypto";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { readJsonFile } from "./utils/jsonFile.js";
6
+ import { DATA_DIR_NAME, dataPath, getProjectRoot, readRenamedEnv, remapLegacyPath, } from "./paths.js";
7
+ import { writeSecretFile } from "./utils/secretFile.js";
8
+ const projectRoot = getProjectRoot();
9
+ const defaultEnvPath = path.join(projectRoot, ".env");
10
+ loadEnv({ path: defaultEnvPath, quiet: true });
11
+ // SECTION: Environment variables
12
+ //
13
+ // Product-scoped variables were renamed from GARMIN_* to TRAINBUD_* in 0.3.0.
14
+ // The old names still work and are reported by `deprecatedEnvNames()` so the
15
+ // CLI can warn once. GARMIN_EMAIL / GARMIN_PASSWORD are deliberately unchanged:
16
+ // they name the third-party Connect account the credentials belong to, not this
17
+ // product, and renaming them would make the .env actively misleading.
18
+ const RENAMED_ENV = {
19
+ TRAINBUD_API_KEY: "GARMIN_MCP_API_KEY",
20
+ TRAINBUD_HOST: "GARMIN_MCP_HOST",
21
+ TRAINBUD_PORT: "GARMIN_MCP_PORT",
22
+ TRAINBUD_SESSION_PATH: "GARMIN_SESSION_PATH",
23
+ TRAINBUD_LOG_PATH: "GARMIN_LOG_PATH",
24
+ TRAINBUD_CACHE_PATH: "GARMIN_CACHE_PATH",
25
+ TRAINBUD_PUBLIC_URL: "GARMIN_PUBLIC_URL",
26
+ };
27
+ function readEnv(name) {
28
+ const legacyName = RENAMED_ENV[name];
29
+ if (!legacyName) {
30
+ const value = process.env[name];
31
+ return value === "" ? undefined : value;
32
+ }
33
+ return readRenamedEnv(name, legacyName).value;
34
+ }
35
+ /** Legacy env var names still present in the environment, for a one-time warning. */
36
+ export function deprecatedEnvNames() {
37
+ return Object.entries(RENAMED_ENV)
38
+ .filter(([name, legacyName]) => readRenamedEnv(name, legacyName).usedLegacy)
39
+ .map(([, legacyName]) => legacyName);
40
+ }
41
+ function readNumber(name, fallback) {
42
+ const value = readEnv(name);
43
+ if (!value) {
44
+ return fallback;
45
+ }
46
+ const parsed = Number.parseInt(value, 10);
47
+ return Number.isFinite(parsed) ? parsed : fallback;
48
+ }
49
+ export function getSessionPath() {
50
+ return remapLegacyPath(readEnv("TRAINBUD_SESSION_PATH") ?? dataPath("session.json"));
51
+ }
52
+ export { getProjectRoot };
53
+ export function getEnvFilePath() {
54
+ return defaultEnvPath;
55
+ }
56
+ export function getDistIndexPath() {
57
+ return path.resolve(projectRoot, "dist", "index.js");
58
+ }
59
+ export function generateApiKey() {
60
+ return randomBytes(32).toString("hex");
61
+ }
62
+ /**
63
+ * Quote a value so dotenv reads back exactly what was written.
64
+ *
65
+ * Values were written bare, and dotenv treats an unquoted `#` as the start of a
66
+ * comment: a Garmin password containing one was silently truncated at that
67
+ * character, so setup "succeeded" and every login afterwards failed with bad
68
+ * credentials the user could see were correct. Measured, not assumed --
69
+ * `P=pa#ss` parses back as `pa`.
70
+ *
71
+ * Single quotes are preferred: dotenv does no unescaping inside them, so `#`,
72
+ * `"`, `$`, spaces and backslashes all survive verbatim. Double quotes are the
73
+ * fallback for a value containing a single quote. A value containing both
74
+ * cannot be represented -- dotenv has no escape that works inside either kind --
75
+ * so that is an error rather than a silent corruption.
76
+ */
77
+ export function quoteEnvValue(value) {
78
+ if (!value.includes("'")) {
79
+ return `'${value}'`;
80
+ }
81
+ if (!value.includes('"')) {
82
+ return `"${value}"`;
83
+ }
84
+ throw new Error("A value containing both ' and \" cannot be stored in .env. Change the password, or set it in the environment instead.");
85
+ }
86
+ /** Keys this file writes itself. Anything else in an existing .env is the
87
+ user's and is carried across untouched. */
88
+ const MANAGED_ENV_KEYS = new Set([
89
+ "GARMIN_EMAIL",
90
+ "GARMIN_PASSWORD",
91
+ "TRAINBUD_API_KEY",
92
+ "TRAINBUD_HOST",
93
+ "TRAINBUD_PORT",
94
+ "TRAINBUD_SESSION_PATH",
95
+ "TRAINBUD_LOG_PATH",
96
+ "TRAINBUD_CACHE_PATH",
97
+ "CACHE_TTL_ACTIVITIES",
98
+ "CACHE_TTL_SLEEP",
99
+ "CACHE_TTL_STATS",
100
+ // The pre-0.3.0 names for the same settings, so re-running setup does not
101
+ // resurrect a duplicate under the old name.
102
+ "GARMIN_MCP_API_KEY",
103
+ "GARMIN_MCP_HOST",
104
+ "GARMIN_MCP_PORT",
105
+ "GARMIN_SESSION_PATH",
106
+ "GARMIN_LOG_PATH",
107
+ "GARMIN_CACHE_PATH",
108
+ ]);
109
+ /**
110
+ * Every assignment in an existing .env that this file does not manage.
111
+ *
112
+ * writeEnvFile rebuilt the file from a fixed template, so re-running
113
+ * `trainbud setup` deleted ANTHROPIC_API_KEY and TRAINBUD_PUBLIC_URL outright --
114
+ * a user who had followed the AI setup guide lost their key by running the
115
+ * command the guide tells them to run when something is wrong.
116
+ */
117
+ export function carriedEnvLines(existing) {
118
+ const carried = [];
119
+ for (const line of existing.split(/\r?\n/)) {
120
+ const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
121
+ if (match && !MANAGED_ENV_KEYS.has(match[1])) {
122
+ carried.push(line.trim());
123
+ }
124
+ }
125
+ return carried;
126
+ }
127
+ export function writeEnvFile(credentials) {
128
+ const envPath = getEnvFilePath();
129
+ const existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf8") : "";
130
+ const existingApiKey = existing.match(/^TRAINBUD_API_KEY=(.+)$/m)?.[1]?.trim() ??
131
+ existing.match(/^GARMIN_MCP_API_KEY=(.+)$/m)?.[1]?.trim();
132
+ const apiKey = (credentials.apiKey ?? existingApiKey ?? generateApiKey())
133
+ .replace(/^['"]|['"]$/g, "");
134
+ const carried = carriedEnvLines(existing);
135
+ const lines = [
136
+ "# Connect account these credentials belong to",
137
+ `GARMIN_EMAIL=${quoteEnvValue(credentials.email)}`,
138
+ `GARMIN_PASSWORD=${quoteEnvValue(credentials.password)}`,
139
+ "",
140
+ "# TrainBud server",
141
+ `TRAINBUD_API_KEY=${quoteEnvValue(apiKey)}`,
142
+ "TRAINBUD_HOST=127.0.0.1",
143
+ "TRAINBUD_PORT=3847",
144
+ `TRAINBUD_SESSION_PATH=${DATA_DIR_NAME}/session.json`,
145
+ `TRAINBUD_LOG_PATH=${DATA_DIR_NAME}/server.log`,
146
+ `TRAINBUD_CACHE_PATH=${DATA_DIR_NAME}/cache.db`,
147
+ "CACHE_TTL_ACTIVITIES=1800",
148
+ "CACHE_TTL_SLEEP=7200",
149
+ "CACHE_TTL_STATS=3600",
150
+ "",
151
+ "# Optional — AI features (bring your own key)",
152
+ ...(carried.some((line) => line.startsWith("ANTHROPIC_API_KEY="))
153
+ ? []
154
+ : ["# ANTHROPIC_API_KEY=sk-ant-..."]),
155
+ ...(carried.some((line) => line.startsWith("TRAINBUD_PUBLIC_URL="))
156
+ ? []
157
+ : ["# TRAINBUD_PUBLIC_URL=https://your-tunnel.example.com"]),
158
+ ...(carried.length > 0 ? ["", "# Kept from your previous .env", ...carried] : []),
159
+ "",
160
+ ];
161
+ writeSecretFile(envPath, lines.join("\n"));
162
+ loadEnv({ path: envPath, override: true, quiet: true });
163
+ return envPath;
164
+ }
165
+ let watchSetupProblem = null;
166
+ export const appConfig = {
167
+ get garminEmail() {
168
+ return process.env.GARMIN_EMAIL ?? "";
169
+ },
170
+ get garminPassword() {
171
+ return process.env.GARMIN_PASSWORD ?? "";
172
+ },
173
+ get sessionPath() {
174
+ return getSessionPath();
175
+ },
176
+ get logPath() {
177
+ return remapLegacyPath(readEnv("TRAINBUD_LOG_PATH") ?? dataPath("server.log"));
178
+ },
179
+ get cachePath() {
180
+ return remapLegacyPath(readEnv("TRAINBUD_CACHE_PATH") ?? dataPath("cache.db"));
181
+ },
182
+ get cacheTtlActivities() {
183
+ return readNumber("CACHE_TTL_ACTIVITIES", 1800);
184
+ },
185
+ get cacheTtlSleep() {
186
+ return readNumber("CACHE_TTL_SLEEP", 7200);
187
+ },
188
+ get cacheTtlStats() {
189
+ return readNumber("CACHE_TTL_STATS", 3600);
190
+ },
191
+ get mcpHost() {
192
+ return readEnv("TRAINBUD_HOST") ?? "127.0.0.1";
193
+ },
194
+ get mcpPort() {
195
+ return readNumber("TRAINBUD_PORT", 3847);
196
+ },
197
+ get mcpApiKey() {
198
+ return readEnv("TRAINBUD_API_KEY") ?? "";
199
+ },
200
+ get anthropicApiKey() {
201
+ return process.env.ANTHROPIC_API_KEY ?? "";
202
+ },
203
+ get publicUrl() {
204
+ const envUrl = (readEnv("TRAINBUD_PUBLIC_URL") ?? "").replace(/\/$/, "");
205
+ if (envUrl)
206
+ return envUrl;
207
+ try {
208
+ const data = readJsonFile(dataPath("watch-setup.json"));
209
+ watchSetupProblem = null;
210
+ return (data.serverUrl ?? "").replace(/\/$/, "");
211
+ }
212
+ catch (error) {
213
+ // "The file is not there" and "the file is there and unreadable" are
214
+ // different faults with different fixes, and this getter used to report
215
+ // both as an empty string. Recorded rather than logged, because the
216
+ // logger reads this config and importing it here would be a cycle.
217
+ watchSetupProblem = fs.existsSync(dataPath("watch-setup.json"))
218
+ ? (error instanceof Error ? error.message : String(error))
219
+ : null;
220
+ return "";
221
+ }
222
+ },
223
+ };
224
+ /**
225
+ * Why the watch setup file could not be read, when it exists but is unusable.
226
+ * `null` when it parsed, or when there is simply no file.
227
+ */
228
+ export function watchSetupReadError() {
229
+ return watchSetupProblem;
230
+ }
231
+ export function assertApiKey() {
232
+ if (!appConfig.mcpApiKey) {
233
+ throw new Error('Missing TRAINBUD_API_KEY. Run "trainbud setup" or add TRAINBUD_API_KEY to .env before "trainbud serve".');
234
+ }
235
+ }
236
+ export function assertGarminCredentials() {
237
+ if (!appConfig.garminEmail || !appConfig.garminPassword) {
238
+ throw new Error("Missing GARMIN_EMAIL or GARMIN_PASSWORD. Copy .env.example to .env and add your Connect account credentials.");
239
+ }
240
+ }
241
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { CARD_IDS } from "./profile.js";
2
+ export { getDashboardStatus } from "./dashboardData.js";
3
+ export type { DashboardStatus, DashboardContextRow, DashboardData, } from "./dashboardData.js";
4
+ export declare function renderDashboard(publicUrl?: string): string;
5
+ export declare function renderPairSuccess(code: string, token?: string): string;
6
+ export declare function renderPairError(msg: string, token?: string): string;
7
+ export { CARD_IDS };
8
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAQxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,aAAa,GACd,MAAM,oBAAoB,CAAC;AA+J5B,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAs2B1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAStE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}