steroids-api 0.2.7

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 (328) hide show
  1. package/dist/API/src/index.d.ts +10 -0
  2. package/dist/API/src/index.d.ts.map +1 -0
  3. package/dist/API/src/index.js +130 -0
  4. package/dist/API/src/index.js.map +1 -0
  5. package/dist/API/src/routes/activity.d.ts +7 -0
  6. package/dist/API/src/routes/activity.d.ts.map +1 -0
  7. package/dist/API/src/routes/activity.js +252 -0
  8. package/dist/API/src/routes/activity.js.map +1 -0
  9. package/dist/API/src/routes/config.d.ts +7 -0
  10. package/dist/API/src/routes/config.d.ts.map +1 -0
  11. package/dist/API/src/routes/config.js +521 -0
  12. package/dist/API/src/routes/config.js.map +1 -0
  13. package/dist/API/src/routes/health.d.ts +7 -0
  14. package/dist/API/src/routes/health.d.ts.map +1 -0
  15. package/dist/API/src/routes/health.js +172 -0
  16. package/dist/API/src/routes/health.js.map +1 -0
  17. package/dist/API/src/routes/incidents.d.ts +7 -0
  18. package/dist/API/src/routes/incidents.d.ts.map +1 -0
  19. package/dist/API/src/routes/incidents.js +117 -0
  20. package/dist/API/src/routes/incidents.js.map +1 -0
  21. package/dist/API/src/routes/projects.d.ts +7 -0
  22. package/dist/API/src/routes/projects.d.ts.map +1 -0
  23. package/dist/API/src/routes/projects.js +398 -0
  24. package/dist/API/src/routes/projects.js.map +1 -0
  25. package/dist/API/src/routes/runners.d.ts +7 -0
  26. package/dist/API/src/routes/runners.d.ts.map +1 -0
  27. package/dist/API/src/routes/runners.js +242 -0
  28. package/dist/API/src/routes/runners.js.map +1 -0
  29. package/dist/API/src/routes/tasks.d.ts +7 -0
  30. package/dist/API/src/routes/tasks.d.ts.map +1 -0
  31. package/dist/API/src/routes/tasks.js +1007 -0
  32. package/dist/API/src/routes/tasks.js.map +1 -0
  33. package/dist/API/src/utils/validation.d.ts +22 -0
  34. package/dist/API/src/utils/validation.d.ts.map +1 -0
  35. package/dist/API/src/utils/validation.js +50 -0
  36. package/dist/API/src/utils/validation.js.map +1 -0
  37. package/dist/index.d.ts +10 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +184 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/routes/activity.d.ts +7 -0
  42. package/dist/routes/activity.d.ts.map +1 -0
  43. package/dist/routes/activity.js +252 -0
  44. package/dist/routes/activity.js.map +1 -0
  45. package/dist/routes/config.d.ts +7 -0
  46. package/dist/routes/config.d.ts.map +1 -0
  47. package/dist/routes/config.js +647 -0
  48. package/dist/routes/config.js.map +1 -0
  49. package/dist/routes/credit-alerts.d.ts +2 -0
  50. package/dist/routes/credit-alerts.d.ts.map +1 -0
  51. package/dist/routes/credit-alerts.js +97 -0
  52. package/dist/routes/credit-alerts.js.map +1 -0
  53. package/dist/routes/health.d.ts +7 -0
  54. package/dist/routes/health.d.ts.map +1 -0
  55. package/dist/routes/health.js +200 -0
  56. package/dist/routes/health.js.map +1 -0
  57. package/dist/routes/incidents.d.ts +7 -0
  58. package/dist/routes/incidents.d.ts.map +1 -0
  59. package/dist/routes/incidents.js +117 -0
  60. package/dist/routes/incidents.js.map +1 -0
  61. package/dist/routes/projects.d.ts +7 -0
  62. package/dist/routes/projects.d.ts.map +1 -0
  63. package/dist/routes/projects.js +643 -0
  64. package/dist/routes/projects.js.map +1 -0
  65. package/dist/routes/runners.d.ts +7 -0
  66. package/dist/routes/runners.d.ts.map +1 -0
  67. package/dist/routes/runners.js +299 -0
  68. package/dist/routes/runners.js.map +1 -0
  69. package/dist/routes/skills.d.ts +3 -0
  70. package/dist/routes/skills.d.ts.map +1 -0
  71. package/dist/routes/skills.js +109 -0
  72. package/dist/routes/skills.js.map +1 -0
  73. package/dist/routes/storage.d.ts +7 -0
  74. package/dist/routes/storage.d.ts.map +1 -0
  75. package/dist/routes/storage.js +93 -0
  76. package/dist/routes/storage.js.map +1 -0
  77. package/dist/routes/tasks.d.ts +7 -0
  78. package/dist/routes/tasks.d.ts.map +1 -0
  79. package/dist/routes/tasks.js +1145 -0
  80. package/dist/routes/tasks.js.map +1 -0
  81. package/dist/src/cleanup/invocation-logs.d.ts +30 -0
  82. package/dist/src/cleanup/invocation-logs.d.ts.map +1 -0
  83. package/dist/src/cleanup/invocation-logs.js +66 -0
  84. package/dist/src/cleanup/invocation-logs.js.map +1 -0
  85. package/dist/src/commands/loop-phases.d.ts +11 -0
  86. package/dist/src/commands/loop-phases.d.ts.map +1 -0
  87. package/dist/src/commands/loop-phases.js +304 -0
  88. package/dist/src/commands/loop-phases.js.map +1 -0
  89. package/dist/src/config/loader.d.ts +160 -0
  90. package/dist/src/config/loader.d.ts.map +1 -0
  91. package/dist/src/config/loader.js +276 -0
  92. package/dist/src/config/loader.js.map +1 -0
  93. package/dist/src/database/connection.d.ts +35 -0
  94. package/dist/src/database/connection.d.ts.map +1 -0
  95. package/dist/src/database/connection.js +197 -0
  96. package/dist/src/database/connection.js.map +1 -0
  97. package/dist/src/database/queries.d.ts +220 -0
  98. package/dist/src/database/queries.d.ts.map +1 -0
  99. package/dist/src/database/queries.js +589 -0
  100. package/dist/src/database/queries.js.map +1 -0
  101. package/dist/src/database/schema.d.ts +8 -0
  102. package/dist/src/database/schema.d.ts.map +1 -0
  103. package/dist/src/database/schema.js +184 -0
  104. package/dist/src/database/schema.js.map +1 -0
  105. package/dist/src/git/push.d.ts +26 -0
  106. package/dist/src/git/push.d.ts.map +1 -0
  107. package/dist/src/git/push.js +91 -0
  108. package/dist/src/git/push.js.map +1 -0
  109. package/dist/src/git/status.d.ts +83 -0
  110. package/dist/src/git/status.d.ts.map +1 -0
  111. package/dist/src/git/status.js +315 -0
  112. package/dist/src/git/status.js.map +1 -0
  113. package/dist/src/health/stuck-task-detector.d.ts +131 -0
  114. package/dist/src/health/stuck-task-detector.d.ts.map +1 -0
  115. package/dist/src/health/stuck-task-detector.js +233 -0
  116. package/dist/src/health/stuck-task-detector.js.map +1 -0
  117. package/dist/src/health/stuck-task-recovery.d.ts +45 -0
  118. package/dist/src/health/stuck-task-recovery.d.ts.map +1 -0
  119. package/dist/src/health/stuck-task-recovery.js +309 -0
  120. package/dist/src/health/stuck-task-recovery.js.map +1 -0
  121. package/dist/src/index.d.ts +10 -0
  122. package/dist/src/index.d.ts.map +1 -0
  123. package/dist/src/index.js +130 -0
  124. package/dist/src/index.js.map +1 -0
  125. package/dist/src/locking/queries.d.ts +116 -0
  126. package/dist/src/locking/queries.d.ts.map +1 -0
  127. package/dist/src/locking/queries.js +232 -0
  128. package/dist/src/locking/queries.js.map +1 -0
  129. package/dist/src/locking/section-lock.d.ts +74 -0
  130. package/dist/src/locking/section-lock.d.ts.map +1 -0
  131. package/dist/src/locking/section-lock.js +196 -0
  132. package/dist/src/locking/section-lock.js.map +1 -0
  133. package/dist/src/locking/task-lock.d.ts +92 -0
  134. package/dist/src/locking/task-lock.d.ts.map +1 -0
  135. package/dist/src/locking/task-lock.js +233 -0
  136. package/dist/src/locking/task-lock.js.map +1 -0
  137. package/dist/src/migrations/index.d.ts +7 -0
  138. package/dist/src/migrations/index.d.ts.map +1 -0
  139. package/dist/src/migrations/index.js +9 -0
  140. package/dist/src/migrations/index.js.map +1 -0
  141. package/dist/src/migrations/manifest.d.ts +92 -0
  142. package/dist/src/migrations/manifest.d.ts.map +1 -0
  143. package/dist/src/migrations/manifest.js +255 -0
  144. package/dist/src/migrations/manifest.js.map +1 -0
  145. package/dist/src/migrations/runner.d.ts +84 -0
  146. package/dist/src/migrations/runner.d.ts.map +1 -0
  147. package/dist/src/migrations/runner.js +338 -0
  148. package/dist/src/migrations/runner.js.map +1 -0
  149. package/dist/src/orchestrator/coder.d.ts +32 -0
  150. package/dist/src/orchestrator/coder.d.ts.map +1 -0
  151. package/dist/src/orchestrator/coder.js +170 -0
  152. package/dist/src/orchestrator/coder.js.map +1 -0
  153. package/dist/src/orchestrator/coordinator.d.ts +28 -0
  154. package/dist/src/orchestrator/coordinator.d.ts.map +1 -0
  155. package/dist/src/orchestrator/coordinator.js +252 -0
  156. package/dist/src/orchestrator/coordinator.js.map +1 -0
  157. package/dist/src/orchestrator/fallback-handler.d.ts +24 -0
  158. package/dist/src/orchestrator/fallback-handler.d.ts.map +1 -0
  159. package/dist/src/orchestrator/fallback-handler.js +280 -0
  160. package/dist/src/orchestrator/fallback-handler.js.map +1 -0
  161. package/dist/src/orchestrator/invoke.d.ts +14 -0
  162. package/dist/src/orchestrator/invoke.d.ts.map +1 -0
  163. package/dist/src/orchestrator/invoke.js +76 -0
  164. package/dist/src/orchestrator/invoke.js.map +1 -0
  165. package/dist/src/orchestrator/post-coder.d.ts +10 -0
  166. package/dist/src/orchestrator/post-coder.d.ts.map +1 -0
  167. package/dist/src/orchestrator/post-coder.js +198 -0
  168. package/dist/src/orchestrator/post-coder.js.map +1 -0
  169. package/dist/src/orchestrator/post-reviewer.d.ts +10 -0
  170. package/dist/src/orchestrator/post-reviewer.d.ts.map +1 -0
  171. package/dist/src/orchestrator/post-reviewer.js +199 -0
  172. package/dist/src/orchestrator/post-reviewer.js.map +1 -0
  173. package/dist/src/orchestrator/reviewer.d.ts +35 -0
  174. package/dist/src/orchestrator/reviewer.d.ts.map +1 -0
  175. package/dist/src/orchestrator/reviewer.js +237 -0
  176. package/dist/src/orchestrator/reviewer.js.map +1 -0
  177. package/dist/src/orchestrator/schemas.d.ts +10 -0
  178. package/dist/src/orchestrator/schemas.d.ts.map +1 -0
  179. package/dist/src/orchestrator/schemas.js +81 -0
  180. package/dist/src/orchestrator/schemas.js.map +1 -0
  181. package/dist/src/orchestrator/task-selector.d.ts +102 -0
  182. package/dist/src/orchestrator/task-selector.d.ts.map +1 -0
  183. package/dist/src/orchestrator/task-selector.js +326 -0
  184. package/dist/src/orchestrator/task-selector.js.map +1 -0
  185. package/dist/src/orchestrator/types.d.ts +74 -0
  186. package/dist/src/orchestrator/types.d.ts.map +1 -0
  187. package/dist/src/orchestrator/types.js +5 -0
  188. package/dist/src/orchestrator/types.js.map +1 -0
  189. package/dist/src/prompts/coder.d.ts +36 -0
  190. package/dist/src/prompts/coder.d.ts.map +1 -0
  191. package/dist/src/prompts/coder.js +303 -0
  192. package/dist/src/prompts/coder.js.map +1 -0
  193. package/dist/src/prompts/prompt-helpers.d.ts +51 -0
  194. package/dist/src/prompts/prompt-helpers.d.ts.map +1 -0
  195. package/dist/src/prompts/prompt-helpers.js +299 -0
  196. package/dist/src/prompts/prompt-helpers.js.map +1 -0
  197. package/dist/src/prompts/reviewer.d.ts +40 -0
  198. package/dist/src/prompts/reviewer.d.ts.map +1 -0
  199. package/dist/src/prompts/reviewer.js +416 -0
  200. package/dist/src/prompts/reviewer.js.map +1 -0
  201. package/dist/src/providers/claude.d.ts +53 -0
  202. package/dist/src/providers/claude.d.ts.map +1 -0
  203. package/dist/src/providers/claude.js +227 -0
  204. package/dist/src/providers/claude.js.map +1 -0
  205. package/dist/src/providers/codex.d.ts +53 -0
  206. package/dist/src/providers/codex.d.ts.map +1 -0
  207. package/dist/src/providers/codex.js +253 -0
  208. package/dist/src/providers/codex.js.map +1 -0
  209. package/dist/src/providers/gemini.d.ts +58 -0
  210. package/dist/src/providers/gemini.d.ts.map +1 -0
  211. package/dist/src/providers/gemini.js +240 -0
  212. package/dist/src/providers/gemini.js.map +1 -0
  213. package/dist/src/providers/interface.d.ts +185 -0
  214. package/dist/src/providers/interface.d.ts.map +1 -0
  215. package/dist/src/providers/interface.js +92 -0
  216. package/dist/src/providers/interface.js.map +1 -0
  217. package/dist/src/providers/invocation-logger.d.ts +97 -0
  218. package/dist/src/providers/invocation-logger.d.ts.map +1 -0
  219. package/dist/src/providers/invocation-logger.js +378 -0
  220. package/dist/src/providers/invocation-logger.js.map +1 -0
  221. package/dist/src/providers/openai.d.ts +53 -0
  222. package/dist/src/providers/openai.d.ts.map +1 -0
  223. package/dist/src/providers/openai.js +230 -0
  224. package/dist/src/providers/openai.js.map +1 -0
  225. package/dist/src/providers/registry.d.ts +100 -0
  226. package/dist/src/providers/registry.d.ts.map +1 -0
  227. package/dist/src/providers/registry.js +170 -0
  228. package/dist/src/providers/registry.js.map +1 -0
  229. package/dist/src/routes/activity.d.ts +7 -0
  230. package/dist/src/routes/activity.d.ts.map +1 -0
  231. package/dist/src/routes/activity.js +252 -0
  232. package/dist/src/routes/activity.js.map +1 -0
  233. package/dist/src/routes/config.d.ts +7 -0
  234. package/dist/src/routes/config.d.ts.map +1 -0
  235. package/dist/src/routes/config.js +521 -0
  236. package/dist/src/routes/config.js.map +1 -0
  237. package/dist/src/routes/health.d.ts +7 -0
  238. package/dist/src/routes/health.d.ts.map +1 -0
  239. package/dist/src/routes/health.js +172 -0
  240. package/dist/src/routes/health.js.map +1 -0
  241. package/dist/src/routes/incidents.d.ts +7 -0
  242. package/dist/src/routes/incidents.d.ts.map +1 -0
  243. package/dist/src/routes/incidents.js +117 -0
  244. package/dist/src/routes/incidents.js.map +1 -0
  245. package/dist/src/routes/projects.d.ts +7 -0
  246. package/dist/src/routes/projects.d.ts.map +1 -0
  247. package/dist/src/routes/projects.js +398 -0
  248. package/dist/src/routes/projects.js.map +1 -0
  249. package/dist/src/routes/runners.d.ts +7 -0
  250. package/dist/src/routes/runners.d.ts.map +1 -0
  251. package/dist/src/routes/runners.js +242 -0
  252. package/dist/src/routes/runners.js.map +1 -0
  253. package/dist/src/routes/tasks.d.ts +7 -0
  254. package/dist/src/routes/tasks.d.ts.map +1 -0
  255. package/dist/src/routes/tasks.js +1007 -0
  256. package/dist/src/routes/tasks.js.map +1 -0
  257. package/dist/src/runners/activity-log.d.ts +65 -0
  258. package/dist/src/runners/activity-log.d.ts.map +1 -0
  259. package/dist/src/runners/activity-log.js +140 -0
  260. package/dist/src/runners/activity-log.js.map +1 -0
  261. package/dist/src/runners/cron.d.ts +30 -0
  262. package/dist/src/runners/cron.d.ts.map +1 -0
  263. package/dist/src/runners/cron.js +333 -0
  264. package/dist/src/runners/cron.js.map +1 -0
  265. package/dist/src/runners/daemon.d.ts +71 -0
  266. package/dist/src/runners/daemon.d.ts.map +1 -0
  267. package/dist/src/runners/daemon.js +233 -0
  268. package/dist/src/runners/daemon.js.map +1 -0
  269. package/dist/src/runners/global-db.d.ts +31 -0
  270. package/dist/src/runners/global-db.d.ts.map +1 -0
  271. package/dist/src/runners/global-db.js +220 -0
  272. package/dist/src/runners/global-db.js.map +1 -0
  273. package/dist/src/runners/hang-detector.d.ts +38 -0
  274. package/dist/src/runners/hang-detector.d.ts.map +1 -0
  275. package/dist/src/runners/hang-detector.js +130 -0
  276. package/dist/src/runners/hang-detector.js.map +1 -0
  277. package/dist/src/runners/heartbeat.d.ts +39 -0
  278. package/dist/src/runners/heartbeat.d.ts.map +1 -0
  279. package/dist/src/runners/heartbeat.js +71 -0
  280. package/dist/src/runners/heartbeat.js.map +1 -0
  281. package/dist/src/runners/lock.d.ts +47 -0
  282. package/dist/src/runners/lock.d.ts.map +1 -0
  283. package/dist/src/runners/lock.js +140 -0
  284. package/dist/src/runners/lock.js.map +1 -0
  285. package/dist/src/runners/orchestrator-loop.d.ts +20 -0
  286. package/dist/src/runners/orchestrator-loop.d.ts.map +1 -0
  287. package/dist/src/runners/orchestrator-loop.js +208 -0
  288. package/dist/src/runners/orchestrator-loop.js.map +1 -0
  289. package/dist/src/runners/projects.d.ts +96 -0
  290. package/dist/src/runners/projects.d.ts.map +1 -0
  291. package/dist/src/runners/projects.js +243 -0
  292. package/dist/src/runners/projects.js.map +1 -0
  293. package/dist/src/runners/wakeup.d.ts +37 -0
  294. package/dist/src/runners/wakeup.d.ts.map +1 -0
  295. package/dist/src/runners/wakeup.js +355 -0
  296. package/dist/src/runners/wakeup.js.map +1 -0
  297. package/dist/src/utils/validation.d.ts +22 -0
  298. package/dist/src/utils/validation.d.ts.map +1 -0
  299. package/dist/src/utils/validation.js +50 -0
  300. package/dist/src/utils/validation.js.map +1 -0
  301. package/dist/utils/sqlite.d.ts +17 -0
  302. package/dist/utils/sqlite.d.ts.map +1 -0
  303. package/dist/utils/sqlite.js +27 -0
  304. package/dist/utils/sqlite.js.map +1 -0
  305. package/dist/utils/storage-cache.d.ts +33 -0
  306. package/dist/utils/storage-cache.d.ts.map +1 -0
  307. package/dist/utils/storage-cache.js +81 -0
  308. package/dist/utils/storage-cache.js.map +1 -0
  309. package/dist/utils/validation.d.ts +22 -0
  310. package/dist/utils/validation.d.ts.map +1 -0
  311. package/dist/utils/validation.js +51 -0
  312. package/dist/utils/validation.js.map +1 -0
  313. package/package.json +39 -0
  314. package/src/index.ts +199 -0
  315. package/src/routes/activity.ts +302 -0
  316. package/src/routes/config.ts +723 -0
  317. package/src/routes/credit-alerts.ts +73 -0
  318. package/src/routes/health.ts +219 -0
  319. package/src/routes/incidents.ts +131 -0
  320. package/src/routes/projects.ts +854 -0
  321. package/src/routes/runners.ts +357 -0
  322. package/src/routes/skills.ts +127 -0
  323. package/src/routes/storage.ts +108 -0
  324. package/src/routes/tasks.ts +1372 -0
  325. package/src/utils/sqlite.ts +36 -0
  326. package/src/utils/storage-cache.ts +107 -0
  327. package/src/utils/validation.ts +61 -0
  328. package/tsconfig.json +20 -0
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Migration manifest management
3
+ * Handles reading, parsing, and validating the migration manifest
4
+ */
5
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
6
+ import { join, dirname } from 'node:path';
7
+ import { createHash } from 'node:crypto';
8
+ import { homedir } from 'node:os';
9
+ // Cache for package root to avoid repeated filesystem operations
10
+ let _packageRoot = null;
11
+ /**
12
+ * Get the CLI package root directory
13
+ * Works whether running from src/ or dist/
14
+ */
15
+ function getPackageRoot() {
16
+ if (_packageRoot)
17
+ return _packageRoot;
18
+ // Try multiple strategies to find the package root
19
+ const candidates = [];
20
+ // Strategy 1: Check process.argv[1] - this is the executed script path
21
+ if (process.argv[1]) {
22
+ let dir = dirname(process.argv[1]);
23
+ for (let i = 0; i < 5; i++) {
24
+ candidates.push(dir);
25
+ dir = dirname(dir);
26
+ }
27
+ }
28
+ // Strategy 2: Check require.main.filename if available
29
+ // In ESM, `require` is not defined, so guard with typeof.
30
+ if (typeof require !== 'undefined' && require.main?.filename) {
31
+ let dir = dirname(require.main.filename);
32
+ for (let i = 0; i < 5; i++) {
33
+ candidates.push(dir);
34
+ dir = dirname(dir);
35
+ }
36
+ }
37
+ // Strategy 3: Check __dirname of this module (works in CommonJS)
38
+ // In compiled output this will be dist/migrations/
39
+ if (typeof __dirname !== 'undefined') {
40
+ let dir = __dirname;
41
+ for (let i = 0; i < 5; i++) {
42
+ candidates.push(dir);
43
+ dir = dirname(dir);
44
+ }
45
+ }
46
+ // Find the first candidate that contains package.json with name 'steroids-cli'
47
+ for (const dir of candidates) {
48
+ const pkgPath = join(dir, 'package.json');
49
+ if (existsSync(pkgPath)) {
50
+ try {
51
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
52
+ if (pkg.name === 'steroids-cli') {
53
+ _packageRoot = dir;
54
+ return dir;
55
+ }
56
+ }
57
+ catch { /* ignore */ }
58
+ }
59
+ }
60
+ // Last resort: try cwd (useful during development)
61
+ const cwdPkg = join(process.cwd(), 'package.json');
62
+ if (existsSync(cwdPkg)) {
63
+ try {
64
+ const pkg = JSON.parse(readFileSync(cwdPkg, 'utf-8'));
65
+ if (pkg.name === 'steroids-cli') {
66
+ _packageRoot = process.cwd();
67
+ return process.cwd();
68
+ }
69
+ }
70
+ catch { /* ignore */ }
71
+ }
72
+ throw new Error('Could not locate steroids-cli package root');
73
+ }
74
+ const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours
75
+ const GLOBAL_STEROIDS_DIR = join(homedir(), '.steroids');
76
+ const CACHE_DIR = join(GLOBAL_STEROIDS_DIR, 'migrations');
77
+ const CACHE_FILE = join(CACHE_DIR, 'manifest-cache.json');
78
+ /**
79
+ * Get the path to the bundled manifest (in the package)
80
+ */
81
+ export function getBundledManifestPath() {
82
+ // Resolve relative to CLI package root, not cwd
83
+ return join(getPackageRoot(), 'migrations', 'manifest.json');
84
+ }
85
+ /**
86
+ * Get the path to a migration file (in the package)
87
+ */
88
+ export function getMigrationFilePath(filename) {
89
+ return join(getPackageRoot(), 'migrations', filename);
90
+ }
91
+ /**
92
+ * Get the path to the cached manifest
93
+ */
94
+ export function getCachedManifestPath() {
95
+ return join(CACHE_DIR, 'manifest.json');
96
+ }
97
+ /**
98
+ * Read the bundled manifest from the package
99
+ */
100
+ export function readBundledManifest() {
101
+ const manifestPath = getBundledManifestPath();
102
+ if (!existsSync(manifestPath)) {
103
+ throw new Error(`Bundled manifest not found at: ${manifestPath}`);
104
+ }
105
+ const content = readFileSync(manifestPath, 'utf-8');
106
+ return parseManifest(content);
107
+ }
108
+ /**
109
+ * Read the cached manifest if it exists and is valid
110
+ */
111
+ export function readCachedManifest() {
112
+ if (!existsSync(CACHE_FILE)) {
113
+ return null;
114
+ }
115
+ try {
116
+ const cacheContent = readFileSync(CACHE_FILE, 'utf-8');
117
+ const cache = JSON.parse(cacheContent);
118
+ // Check if cache is still valid
119
+ if (Date.now() - cache.fetchedAt > CACHE_TTL) {
120
+ return null;
121
+ }
122
+ return cache.manifest;
123
+ }
124
+ catch {
125
+ return null;
126
+ }
127
+ }
128
+ /**
129
+ * Save manifest to cache
130
+ */
131
+ export function cacheManifest(manifest) {
132
+ if (!existsSync(CACHE_DIR)) {
133
+ mkdirSync(CACHE_DIR, { recursive: true });
134
+ }
135
+ const cache = {
136
+ fetchedAt: Date.now(),
137
+ manifest,
138
+ };
139
+ writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
140
+ // Also save the manifest itself for offline access
141
+ writeFileSync(getCachedManifestPath(), JSON.stringify(manifest, null, 2));
142
+ }
143
+ /**
144
+ * Parse and validate manifest content
145
+ */
146
+ export function parseManifest(content) {
147
+ const manifest = JSON.parse(content);
148
+ validateManifest(manifest);
149
+ return manifest;
150
+ }
151
+ /**
152
+ * Validate manifest structure
153
+ */
154
+ export function validateManifest(manifest) {
155
+ if (!manifest.version) {
156
+ throw new Error('Manifest missing version field');
157
+ }
158
+ if (typeof manifest.latestDbVersion !== 'number' || manifest.latestDbVersion < 1) {
159
+ throw new Error('Manifest missing or invalid latestDbVersion field');
160
+ }
161
+ if (!Array.isArray(manifest.migrations)) {
162
+ throw new Error('Manifest missing migrations array');
163
+ }
164
+ // Validate each migration entry
165
+ for (const migration of manifest.migrations) {
166
+ validateMigrationEntry(migration);
167
+ }
168
+ // Validate migrations are in order
169
+ const ids = manifest.migrations.map(m => m.id);
170
+ for (let i = 1; i < ids.length; i++) {
171
+ if (ids[i] <= ids[i - 1]) {
172
+ throw new Error(`Migrations not in order: ${ids[i - 1]} followed by ${ids[i]}`);
173
+ }
174
+ }
175
+ // Validate latestDbVersion matches
176
+ if (manifest.migrations.length > 0) {
177
+ const maxId = Math.max(...ids);
178
+ if (maxId !== manifest.latestDbVersion) {
179
+ throw new Error(`latestDbVersion (${manifest.latestDbVersion}) does not match highest migration id (${maxId})`);
180
+ }
181
+ }
182
+ }
183
+ /**
184
+ * Validate a single migration entry
185
+ */
186
+ function validateMigrationEntry(entry) {
187
+ if (typeof entry.id !== 'number' || entry.id < 1) {
188
+ throw new Error(`Invalid migration id: ${entry.id}`);
189
+ }
190
+ if (!entry.name || typeof entry.name !== 'string') {
191
+ throw new Error(`Migration ${entry.id} missing name`);
192
+ }
193
+ if (!entry.file || typeof entry.file !== 'string') {
194
+ throw new Error(`Migration ${entry.id} missing file`);
195
+ }
196
+ if (!entry.description || typeof entry.description !== 'string') {
197
+ throw new Error(`Migration ${entry.id} missing description`);
198
+ }
199
+ if (!entry.cliVersion || typeof entry.cliVersion !== 'string') {
200
+ throw new Error(`Migration ${entry.id} missing cliVersion`);
201
+ }
202
+ // Checksum can be empty for new migrations
203
+ }
204
+ /**
205
+ * Calculate SHA256 checksum for migration file content
206
+ */
207
+ export function calculateChecksum(content) {
208
+ const hash = createHash('sha256');
209
+ hash.update(content);
210
+ return `sha256:${hash.digest('hex')}`;
211
+ }
212
+ /**
213
+ * Verify checksum matches
214
+ */
215
+ export function verifyChecksum(content, expectedChecksum) {
216
+ if (!expectedChecksum) {
217
+ // No checksum to verify
218
+ return true;
219
+ }
220
+ const actual = calculateChecksum(content);
221
+ return actual === expectedChecksum;
222
+ }
223
+ /**
224
+ * Find pending migrations that need to be applied
225
+ */
226
+ export function findPendingMigrations(manifest, appliedMigrations) {
227
+ const appliedIds = new Set(appliedMigrations.map(m => m.id));
228
+ return manifest.migrations.filter(m => !appliedIds.has(m.id));
229
+ }
230
+ /**
231
+ * Find migrations to rollback (applied but not in manifest)
232
+ */
233
+ export function findOrphanedMigrations(manifest, appliedMigrations) {
234
+ const manifestIds = new Set(manifest.migrations.map(m => m.id));
235
+ return appliedMigrations.filter(m => !manifestIds.has(m.id));
236
+ }
237
+ /**
238
+ * Get migration entry by ID
239
+ */
240
+ export function getMigrationById(manifest, id) {
241
+ return manifest.migrations.find(m => m.id === id) ?? null;
242
+ }
243
+ /**
244
+ * Get the current supported database version range for this CLI
245
+ */
246
+ export function getCliSupportedVersions(manifest) {
247
+ if (manifest.migrations.length === 0) {
248
+ return { min: 0, max: 0 };
249
+ }
250
+ return {
251
+ min: 1, // Always support from version 1
252
+ max: manifest.latestDbVersion,
253
+ };
254
+ }
255
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../src/migrations/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Migration runner
3
+ * Applies and rolls back database migrations with transaction safety
4
+ */
5
+ import Database from 'better-sqlite3';
6
+ import { MigrationManifest, MigrationEntry, AppliedMigration } from './manifest.js';
7
+ /**
8
+ * Result of a migration operation
9
+ */
10
+ export interface MigrationResult {
11
+ success: boolean;
12
+ applied: string[];
13
+ failed?: string;
14
+ error?: string;
15
+ }
16
+ /**
17
+ * Migration SQL sections
18
+ */
19
+ interface MigrationSql {
20
+ up: string;
21
+ down: string;
22
+ }
23
+ /**
24
+ * Parse migration file into UP and DOWN sections
25
+ */
26
+ export declare function parseMigrationFile(content: string): MigrationSql;
27
+ /**
28
+ * Read migration file content
29
+ */
30
+ export declare function readMigrationFile(entry: MigrationEntry): string;
31
+ /**
32
+ * Get applied migrations from database
33
+ */
34
+ export declare function getAppliedMigrations(db: Database.Database): AppliedMigration[];
35
+ /**
36
+ * Get current database version
37
+ */
38
+ export declare function getDatabaseVersion(db: Database.Database): number;
39
+ /**
40
+ * Create backup of database before migration
41
+ */
42
+ export declare function createBackup(dbPath: string): string;
43
+ /**
44
+ * Apply a single migration
45
+ * Handles idempotent migrations (e.g., duplicate column errors are treated as success)
46
+ */
47
+ export declare function applyMigration(db: Database.Database, entry: MigrationEntry, content: string): void;
48
+ /**
49
+ * Rollback a single migration
50
+ */
51
+ export declare function rollbackMigration(db: Database.Database, entry: MigrationEntry, content: string): void;
52
+ /**
53
+ * Run all pending migrations
54
+ */
55
+ export declare function runMigrations(db: Database.Database, manifest: MigrationManifest, options?: {
56
+ toVersion?: number;
57
+ dryRun?: boolean;
58
+ }): MigrationResult;
59
+ /**
60
+ * Rollback to a specific version
61
+ */
62
+ export declare function rollbackToVersion(db: Database.Database, manifest: MigrationManifest, targetVersion: number): MigrationResult;
63
+ /**
64
+ * Get migration status
65
+ */
66
+ export interface MigrationStatus {
67
+ currentVersion: number;
68
+ latestVersion: number;
69
+ isUpToDate: boolean;
70
+ pending: MigrationEntry[];
71
+ applied: AppliedMigration[];
72
+ }
73
+ export declare function getMigrationStatus(db: Database.Database, manifest: MigrationManifest): MigrationStatus;
74
+ /**
75
+ * Check and apply any pending migrations automatically
76
+ * Returns true if migrations were applied, false if already up to date
77
+ */
78
+ export declare function autoMigrate(db: Database.Database, dbPath?: string): {
79
+ applied: boolean;
80
+ migrations: string[];
81
+ error?: string;
82
+ };
83
+ export {};
84
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/migrations/runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAMjB,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA8BhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAQ/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,gBAAgB,EAAE,CAQ9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAiBhE;AA4BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAyBnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CAwCN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CA4BN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CACb,GACL,eAAe,CA+CjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,MAAM,GACpB,eAAe,CA8CjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,eAAe,CAYjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAyCA"}
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Migration runner
3
+ * Applies and rolls back database migrations with transaction safety
4
+ */
5
+ import { readFileSync, existsSync, copyFileSync, mkdirSync } from 'node:fs';
6
+ import { join, dirname } from 'node:path';
7
+ import { readBundledManifest, getMigrationFilePath, calculateChecksum, verifyChecksum, findPendingMigrations, } from './manifest.js';
8
+ /**
9
+ * Parse migration file into UP and DOWN sections
10
+ */
11
+ export function parseMigrationFile(content) {
12
+ const lines = content.split('\n');
13
+ let currentSection = 'none';
14
+ const upLines = [];
15
+ const downLines = [];
16
+ for (const line of lines) {
17
+ const trimmed = line.trim().toUpperCase();
18
+ if (trimmed === '-- UP') {
19
+ currentSection = 'up';
20
+ continue;
21
+ }
22
+ if (trimmed === '-- DOWN') {
23
+ currentSection = 'down';
24
+ continue;
25
+ }
26
+ if (currentSection === 'up') {
27
+ upLines.push(line);
28
+ }
29
+ else if (currentSection === 'down') {
30
+ downLines.push(line);
31
+ }
32
+ }
33
+ return {
34
+ up: upLines.join('\n').trim(),
35
+ down: downLines.join('\n').trim(),
36
+ };
37
+ }
38
+ /**
39
+ * Read migration file content
40
+ */
41
+ export function readMigrationFile(entry) {
42
+ const filePath = getMigrationFilePath(entry.file);
43
+ if (!existsSync(filePath)) {
44
+ throw new Error(`Migration file not found: ${filePath}`);
45
+ }
46
+ return readFileSync(filePath, 'utf-8');
47
+ }
48
+ /**
49
+ * Get applied migrations from database
50
+ */
51
+ export function getAppliedMigrations(db) {
52
+ try {
53
+ const rows = db.prepare('SELECT id, name, checksum, applied_at FROM _migrations ORDER BY id').all();
54
+ return rows;
55
+ }
56
+ catch {
57
+ // Table may not exist yet
58
+ return [];
59
+ }
60
+ }
61
+ /**
62
+ * Get current database version
63
+ */
64
+ export function getDatabaseVersion(db) {
65
+ try {
66
+ const row = db.prepare('SELECT value FROM _schema WHERE key = ?').get('version');
67
+ if (!row)
68
+ return 0;
69
+ // Parse version - could be semver "0.1.0" or just a number
70
+ const version = row.value;
71
+ if (/^\d+$/.test(version)) {
72
+ return parseInt(version, 10);
73
+ }
74
+ // For semver, use the number of applied migrations as the version
75
+ const migrations = getAppliedMigrations(db);
76
+ return migrations.length;
77
+ }
78
+ catch {
79
+ return 0;
80
+ }
81
+ }
82
+ /**
83
+ * Update database version in _schema table
84
+ */
85
+ function updateDatabaseVersion(db, version, migrationName) {
86
+ db.prepare('INSERT OR REPLACE INTO _schema (key, value) VALUES (?, ?)').run('version', version.toString());
87
+ db.prepare('INSERT OR REPLACE INTO _schema (key, value) VALUES (?, ?)').run('last_migration', migrationName);
88
+ }
89
+ /**
90
+ * Record applied migration
91
+ */
92
+ function recordMigration(db, entry, checksum) {
93
+ db.prepare('INSERT INTO _migrations (id, name, checksum) VALUES (?, ?, ?)').run(entry.id, entry.name, checksum);
94
+ }
95
+ /**
96
+ * Remove migration record (for rollback)
97
+ */
98
+ function removeMigrationRecord(db, id) {
99
+ db.prepare('DELETE FROM _migrations WHERE id = ?').run(id);
100
+ }
101
+ /**
102
+ * Create backup of database before migration
103
+ */
104
+ export function createBackup(dbPath) {
105
+ const steroidsDir = dirname(dbPath);
106
+ const backupDir = join(steroidsDir, 'backup');
107
+ if (!existsSync(backupDir)) {
108
+ mkdirSync(backupDir, { recursive: true });
109
+ }
110
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
111
+ const backupPath = join(backupDir, `pre-migrate-${timestamp}.db`);
112
+ copyFileSync(dbPath, backupPath);
113
+ // Also copy WAL and SHM files if they exist
114
+ const walPath = `${dbPath}-wal`;
115
+ const shmPath = `${dbPath}-shm`;
116
+ if (existsSync(walPath)) {
117
+ copyFileSync(walPath, `${backupPath}-wal`);
118
+ }
119
+ if (existsSync(shmPath)) {
120
+ copyFileSync(shmPath, `${backupPath}-shm`);
121
+ }
122
+ return backupPath;
123
+ }
124
+ /**
125
+ * Apply a single migration
126
+ * Handles idempotent migrations (e.g., duplicate column errors are treated as success)
127
+ */
128
+ export function applyMigration(db, entry, content) {
129
+ const parsed = parseMigrationFile(content);
130
+ const checksum = calculateChecksum(content);
131
+ if (entry.checksum && !verifyChecksum(content, entry.checksum)) {
132
+ throw new Error(`Checksum mismatch for migration ${entry.name}. ` +
133
+ `Expected ${entry.checksum}, got ${checksum}. ` +
134
+ 'The migration file may have been corrupted or tampered with.');
135
+ }
136
+ if (!parsed.up) {
137
+ throw new Error(`Migration ${entry.name} has no UP section`);
138
+ }
139
+ // Apply the migration in a transaction
140
+ // Handle idempotent cases like "duplicate column name" or "table already exists"
141
+ const transaction = db.transaction(() => {
142
+ try {
143
+ db.exec(parsed.up);
144
+ }
145
+ catch (err) {
146
+ const msg = err instanceof Error ? err.message : String(err);
147
+ // These errors indicate the migration was already effectively applied
148
+ const idempotentErrors = [
149
+ 'duplicate column name',
150
+ 'table already exists',
151
+ 'index already exists',
152
+ ];
153
+ const isIdempotent = idempotentErrors.some(e => msg.toLowerCase().includes(e));
154
+ if (!isIdempotent) {
155
+ throw err;
156
+ }
157
+ // Migration already applied, continue to record it
158
+ }
159
+ recordMigration(db, entry, checksum);
160
+ updateDatabaseVersion(db, entry.id, entry.name);
161
+ });
162
+ transaction();
163
+ }
164
+ /**
165
+ * Rollback a single migration
166
+ */
167
+ export function rollbackMigration(db, entry, content) {
168
+ const parsed = parseMigrationFile(content);
169
+ if (!parsed.down) {
170
+ throw new Error(`Migration ${entry.name} has no DOWN section - cannot rollback`);
171
+ }
172
+ // Rollback in a transaction
173
+ const transaction = db.transaction(() => {
174
+ db.exec(parsed.down);
175
+ removeMigrationRecord(db, entry.id);
176
+ // Update version to previous migration
177
+ const previousId = entry.id - 1;
178
+ if (previousId > 0) {
179
+ const manifest = readBundledManifest();
180
+ const previousMigration = manifest.migrations.find(m => m.id === previousId);
181
+ if (previousMigration) {
182
+ updateDatabaseVersion(db, previousId, previousMigration.name);
183
+ }
184
+ }
185
+ else {
186
+ // No more migrations, set version to 0
187
+ db.prepare('DELETE FROM _schema WHERE key = ?').run('version');
188
+ db.prepare('DELETE FROM _schema WHERE key = ?').run('last_migration');
189
+ }
190
+ });
191
+ transaction();
192
+ }
193
+ /**
194
+ * Run all pending migrations
195
+ */
196
+ export function runMigrations(db, manifest, options = {}) {
197
+ const applied = getAppliedMigrations(db);
198
+ const pending = findPendingMigrations(manifest, applied);
199
+ // Filter by target version if specified
200
+ const migrationsToApply = options.toVersion
201
+ ? pending.filter(m => m.id <= options.toVersion)
202
+ : pending;
203
+ if (migrationsToApply.length === 0) {
204
+ return {
205
+ success: true,
206
+ applied: [],
207
+ };
208
+ }
209
+ // Sort by ID to ensure correct order
210
+ migrationsToApply.sort((a, b) => a.id - b.id);
211
+ if (options.dryRun) {
212
+ return {
213
+ success: true,
214
+ applied: migrationsToApply.map(m => m.name),
215
+ };
216
+ }
217
+ const appliedNames = [];
218
+ for (const migration of migrationsToApply) {
219
+ try {
220
+ const content = readMigrationFile(migration);
221
+ applyMigration(db, migration, content);
222
+ appliedNames.push(migration.name);
223
+ }
224
+ catch (error) {
225
+ return {
226
+ success: false,
227
+ applied: appliedNames,
228
+ failed: migration.name,
229
+ error: error instanceof Error ? error.message : String(error),
230
+ };
231
+ }
232
+ }
233
+ return {
234
+ success: true,
235
+ applied: appliedNames,
236
+ };
237
+ }
238
+ /**
239
+ * Rollback to a specific version
240
+ */
241
+ export function rollbackToVersion(db, manifest, targetVersion) {
242
+ const applied = getAppliedMigrations(db);
243
+ // Find migrations to rollback (those with id > targetVersion)
244
+ const toRollback = applied
245
+ .filter(m => m.id > targetVersion)
246
+ .sort((a, b) => b.id - a.id); // Rollback in reverse order
247
+ if (toRollback.length === 0) {
248
+ return {
249
+ success: true,
250
+ applied: [],
251
+ };
252
+ }
253
+ const rolledBack = [];
254
+ for (const migration of toRollback) {
255
+ const entry = manifest.migrations.find(m => m.id === migration.id);
256
+ if (!entry) {
257
+ return {
258
+ success: false,
259
+ applied: rolledBack,
260
+ failed: migration.name,
261
+ error: `Migration ${migration.name} not found in manifest`,
262
+ };
263
+ }
264
+ try {
265
+ const content = readMigrationFile(entry);
266
+ rollbackMigration(db, entry, content);
267
+ rolledBack.push(migration.name);
268
+ }
269
+ catch (error) {
270
+ return {
271
+ success: false,
272
+ applied: rolledBack,
273
+ failed: migration.name,
274
+ error: error instanceof Error ? error.message : String(error),
275
+ };
276
+ }
277
+ }
278
+ return {
279
+ success: true,
280
+ applied: rolledBack,
281
+ };
282
+ }
283
+ export function getMigrationStatus(db, manifest) {
284
+ const applied = getAppliedMigrations(db);
285
+ const pending = findPendingMigrations(manifest, applied);
286
+ const currentVersion = applied.length > 0 ? Math.max(...applied.map(m => m.id)) : 0;
287
+ return {
288
+ currentVersion,
289
+ latestVersion: manifest.latestDbVersion,
290
+ isUpToDate: pending.length === 0,
291
+ pending,
292
+ applied,
293
+ };
294
+ }
295
+ /**
296
+ * Check and apply any pending migrations automatically
297
+ * Returns true if migrations were applied, false if already up to date
298
+ */
299
+ export function autoMigrate(db, dbPath) {
300
+ try {
301
+ const manifest = readBundledManifest();
302
+ const status = getMigrationStatus(db, manifest);
303
+ if (status.isUpToDate) {
304
+ return { applied: false, migrations: [] };
305
+ }
306
+ // Create backup before migrating if path provided
307
+ if (dbPath) {
308
+ try {
309
+ createBackup(dbPath);
310
+ }
311
+ catch (backupErr) {
312
+ // Log but don't fail - backup is optional
313
+ console.error('Warning: Could not create backup before migration:', backupErr);
314
+ }
315
+ }
316
+ // Apply pending migrations
317
+ const result = runMigrations(db, manifest);
318
+ if (!result.success) {
319
+ return {
320
+ applied: false,
321
+ migrations: result.applied,
322
+ error: `Migration failed at ${result.failed}: ${result.error}`,
323
+ };
324
+ }
325
+ return {
326
+ applied: result.applied.length > 0,
327
+ migrations: result.applied,
328
+ };
329
+ }
330
+ catch (err) {
331
+ return {
332
+ applied: false,
333
+ migrations: [],
334
+ error: err instanceof Error ? err.message : String(err),
335
+ };
336
+ }
337
+ }
338
+ //# sourceMappingURL=runner.js.map