codex-multi-auth 1.1.11 → 1.2.1

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 (695) hide show
  1. package/README.md +52 -20
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1023 -1661
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/accounts.d.ts +22 -2
  6. package/dist/lib/accounts.d.ts.map +1 -1
  7. package/dist/lib/accounts.js +84 -1
  8. package/dist/lib/accounts.js.map +1 -1
  9. package/dist/lib/auth/browser.d.ts +1 -0
  10. package/dist/lib/auth/browser.d.ts.map +1 -1
  11. package/dist/lib/auth/browser.js +13 -0
  12. package/dist/lib/auth/browser.js.map +1 -1
  13. package/dist/lib/auth/index.d.ts +2 -0
  14. package/dist/lib/auth/index.d.ts.map +1 -0
  15. package/dist/lib/auth/index.js +2 -0
  16. package/dist/lib/auth/index.js.map +1 -0
  17. package/dist/lib/auth/token-utils.d.ts +16 -0
  18. package/dist/lib/auth/token-utils.d.ts.map +1 -1
  19. package/dist/lib/auth/token-utils.js +13 -0
  20. package/dist/lib/auth/token-utils.js.map +1 -1
  21. package/dist/lib/codex-cli/index.d.ts +5 -0
  22. package/dist/lib/codex-cli/index.d.ts.map +1 -0
  23. package/dist/lib/codex-cli/index.js +5 -0
  24. package/dist/lib/codex-cli/index.js.map +1 -0
  25. package/dist/lib/codex-manager/auth-commands.d.ts +72 -0
  26. package/dist/lib/codex-manager/auth-commands.d.ts.map +1 -0
  27. package/dist/lib/codex-manager/auth-commands.js +643 -0
  28. package/dist/lib/codex-manager/auth-commands.js.map +1 -0
  29. package/dist/lib/codex-manager/backend-category-entry.d.ts +103 -0
  30. package/dist/lib/codex-manager/backend-category-entry.d.ts.map +1 -0
  31. package/dist/lib/codex-manager/backend-category-entry.js +23 -0
  32. package/dist/lib/codex-manager/backend-category-entry.js.map +1 -0
  33. package/dist/lib/codex-manager/backend-category-helpers.d.ts +10 -0
  34. package/dist/lib/codex-manager/backend-category-helpers.d.ts.map +1 -0
  35. package/dist/lib/codex-manager/backend-category-helpers.js +29 -0
  36. package/dist/lib/codex-manager/backend-category-helpers.js.map +1 -0
  37. package/dist/lib/codex-manager/backend-category-prompt.d.ts +55 -0
  38. package/dist/lib/codex-manager/backend-category-prompt.d.ts.map +1 -0
  39. package/dist/lib/codex-manager/backend-category-prompt.js +178 -0
  40. package/dist/lib/codex-manager/backend-category-prompt.js.map +1 -0
  41. package/dist/lib/codex-manager/backend-settings-controller.d.ts +11 -0
  42. package/dist/lib/codex-manager/backend-settings-controller.d.ts.map +1 -0
  43. package/dist/lib/codex-manager/backend-settings-controller.js +14 -0
  44. package/dist/lib/codex-manager/backend-settings-controller.js.map +1 -0
  45. package/dist/lib/codex-manager/backend-settings-entry.d.ts +20 -0
  46. package/dist/lib/codex-manager/backend-settings-entry.d.ts.map +1 -0
  47. package/dist/lib/codex-manager/backend-settings-entry.js +12 -0
  48. package/dist/lib/codex-manager/backend-settings-entry.js.map +1 -0
  49. package/dist/lib/codex-manager/backend-settings-helpers.d.ts +16 -0
  50. package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +1 -0
  51. package/dist/lib/codex-manager/backend-settings-helpers.js +102 -0
  52. package/dist/lib/codex-manager/backend-settings-helpers.js.map +1 -0
  53. package/dist/lib/codex-manager/backend-settings-prompt.d.ts +49 -0
  54. package/dist/lib/codex-manager/backend-settings-prompt.d.ts.map +1 -0
  55. package/dist/lib/codex-manager/backend-settings-prompt.js +121 -0
  56. package/dist/lib/codex-manager/backend-settings-prompt.js.map +1 -0
  57. package/dist/lib/codex-manager/backend-settings-schema.d.ts +55 -0
  58. package/dist/lib/codex-manager/backend-settings-schema.d.ts.map +1 -0
  59. package/dist/lib/codex-manager/backend-settings-schema.js +264 -0
  60. package/dist/lib/codex-manager/backend-settings-schema.js.map +1 -0
  61. package/dist/lib/codex-manager/behavior-settings-panel.d.ts +33 -0
  62. package/dist/lib/codex-manager/behavior-settings-panel.d.ts.map +1 -0
  63. package/dist/lib/codex-manager/behavior-settings-panel.js +180 -0
  64. package/dist/lib/codex-manager/behavior-settings-panel.js.map +1 -0
  65. package/dist/lib/codex-manager/best.d.ts +26 -0
  66. package/dist/lib/codex-manager/best.d.ts.map +1 -0
  67. package/dist/lib/codex-manager/best.js +249 -0
  68. package/dist/lib/codex-manager/best.js.map +1 -0
  69. package/dist/lib/codex-manager/commands/best.d.ts +81 -0
  70. package/dist/lib/codex-manager/commands/best.d.ts.map +1 -0
  71. package/dist/lib/codex-manager/commands/best.js +223 -0
  72. package/dist/lib/codex-manager/commands/best.js.map +1 -0
  73. package/dist/lib/codex-manager/commands/check.d.ts +7 -0
  74. package/dist/lib/codex-manager/commands/check.d.ts.map +1 -0
  75. package/dist/lib/codex-manager/commands/check.js +5 -0
  76. package/dist/lib/codex-manager/commands/check.js.map +1 -0
  77. package/dist/lib/codex-manager/commands/config-explain.d.ts +7 -0
  78. package/dist/lib/codex-manager/commands/config-explain.d.ts.map +1 -0
  79. package/dist/lib/codex-manager/commands/config-explain.js +31 -0
  80. package/dist/lib/codex-manager/commands/config-explain.js.map +1 -0
  81. package/dist/lib/codex-manager/commands/debug-bundle.d.ts +28 -0
  82. package/dist/lib/codex-manager/commands/debug-bundle.d.ts.map +1 -0
  83. package/dist/lib/codex-manager/commands/debug-bundle.js +62 -0
  84. package/dist/lib/codex-manager/commands/debug-bundle.js.map +1 -0
  85. package/dist/lib/codex-manager/commands/doctor.d.ts +85 -0
  86. package/dist/lib/codex-manager/commands/doctor.d.ts.map +1 -0
  87. package/dist/lib/codex-manager/commands/doctor.js +424 -0
  88. package/dist/lib/codex-manager/commands/doctor.js.map +1 -0
  89. package/dist/lib/codex-manager/commands/fix.d.ts +92 -0
  90. package/dist/lib/codex-manager/commands/fix.d.ts.map +1 -0
  91. package/dist/lib/codex-manager/commands/fix.js +347 -0
  92. package/dist/lib/codex-manager/commands/fix.js.map +1 -0
  93. package/dist/lib/codex-manager/commands/forecast.d.ts +70 -0
  94. package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -0
  95. package/dist/lib/codex-manager/commands/forecast.js +281 -0
  96. package/dist/lib/codex-manager/commands/forecast.js.map +1 -0
  97. package/dist/lib/codex-manager/commands/init-config.d.ts +15 -0
  98. package/dist/lib/codex-manager/commands/init-config.d.ts.map +1 -0
  99. package/dist/lib/codex-manager/commands/init-config.js +95 -0
  100. package/dist/lib/codex-manager/commands/init-config.js.map +1 -0
  101. package/dist/lib/codex-manager/commands/report.d.ts +24 -0
  102. package/dist/lib/codex-manager/commands/report.d.ts.map +1 -0
  103. package/dist/lib/codex-manager/commands/report.js +314 -0
  104. package/dist/lib/codex-manager/commands/report.js.map +1 -0
  105. package/dist/lib/codex-manager/commands/status.d.ts +23 -0
  106. package/dist/lib/codex-manager/commands/status.d.ts.map +1 -0
  107. package/dist/lib/codex-manager/commands/status.js +50 -0
  108. package/dist/lib/codex-manager/commands/status.js.map +1 -0
  109. package/dist/lib/codex-manager/commands/switch.d.ts +22 -0
  110. package/dist/lib/codex-manager/commands/switch.d.ts.map +1 -0
  111. package/dist/lib/codex-manager/commands/switch.js +41 -0
  112. package/dist/lib/codex-manager/commands/switch.js.map +1 -0
  113. package/dist/lib/codex-manager/commands/verify-flagged.d.ts +69 -0
  114. package/dist/lib/codex-manager/commands/verify-flagged.d.ts.map +1 -0
  115. package/dist/lib/codex-manager/commands/verify-flagged.js +251 -0
  116. package/dist/lib/codex-manager/commands/verify-flagged.js.map +1 -0
  117. package/dist/lib/codex-manager/config-explain.d.ts +2 -0
  118. package/dist/lib/codex-manager/config-explain.d.ts.map +1 -0
  119. package/dist/lib/codex-manager/config-explain.js +62 -0
  120. package/dist/lib/codex-manager/config-explain.js.map +1 -0
  121. package/dist/lib/codex-manager/config-template.d.ts +2 -0
  122. package/dist/lib/codex-manager/config-template.d.ts.map +1 -0
  123. package/dist/lib/codex-manager/config-template.js +112 -0
  124. package/dist/lib/codex-manager/config-template.js.map +1 -0
  125. package/dist/lib/codex-manager/dashboard-display-panel.d.ts +40 -0
  126. package/dist/lib/codex-manager/dashboard-display-panel.d.ts.map +1 -0
  127. package/dist/lib/codex-manager/dashboard-display-panel.js +187 -0
  128. package/dist/lib/codex-manager/dashboard-display-panel.js.map +1 -0
  129. package/dist/lib/codex-manager/dashboard-formatters.d.ts +6 -0
  130. package/dist/lib/codex-manager/dashboard-formatters.d.ts.map +1 -0
  131. package/dist/lib/codex-manager/dashboard-formatters.js +19 -0
  132. package/dist/lib/codex-manager/dashboard-formatters.js.map +1 -0
  133. package/dist/lib/codex-manager/dashboard-settings-controller.d.ts +12 -0
  134. package/dist/lib/codex-manager/dashboard-settings-controller.d.ts.map +1 -0
  135. package/dist/lib/codex-manager/dashboard-settings-controller.js +17 -0
  136. package/dist/lib/codex-manager/dashboard-settings-controller.js.map +1 -0
  137. package/dist/lib/codex-manager/dashboard-settings-data.d.ts +10 -0
  138. package/dist/lib/codex-manager/dashboard-settings-data.d.ts.map +1 -0
  139. package/dist/lib/codex-manager/dashboard-settings-data.js +95 -0
  140. package/dist/lib/codex-manager/dashboard-settings-data.js.map +1 -0
  141. package/dist/lib/codex-manager/dashboard-settings-entry.d.ts +22 -0
  142. package/dist/lib/codex-manager/dashboard-settings-entry.d.ts.map +1 -0
  143. package/dist/lib/codex-manager/dashboard-settings-entry.js +13 -0
  144. package/dist/lib/codex-manager/dashboard-settings-entry.js.map +1 -0
  145. package/dist/lib/codex-manager/debug-bundle.d.ts +2 -0
  146. package/dist/lib/codex-manager/debug-bundle.d.ts.map +1 -0
  147. package/dist/lib/codex-manager/debug-bundle.js +128 -0
  148. package/dist/lib/codex-manager/debug-bundle.js.map +1 -0
  149. package/dist/lib/codex-manager/doctor.d.ts +20 -0
  150. package/dist/lib/codex-manager/doctor.d.ts.map +1 -0
  151. package/dist/lib/codex-manager/doctor.js +546 -0
  152. package/dist/lib/codex-manager/doctor.js.map +1 -0
  153. package/dist/lib/codex-manager/experimental-settings-entry.d.ts +7 -0
  154. package/dist/lib/codex-manager/experimental-settings-entry.d.ts.map +1 -0
  155. package/dist/lib/codex-manager/experimental-settings-entry.js +30 -0
  156. package/dist/lib/codex-manager/experimental-settings-entry.js.map +1 -0
  157. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +66 -0
  158. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -0
  159. package/dist/lib/codex-manager/experimental-settings-prompt.js +221 -0
  160. package/dist/lib/codex-manager/experimental-settings-prompt.js.map +1 -0
  161. package/dist/lib/codex-manager/experimental-settings-schema.d.ts +23 -0
  162. package/dist/lib/codex-manager/experimental-settings-schema.d.ts.map +1 -0
  163. package/dist/lib/codex-manager/experimental-settings-schema.js +34 -0
  164. package/dist/lib/codex-manager/experimental-settings-schema.js.map +1 -0
  165. package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts +30 -0
  166. package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts.map +1 -0
  167. package/dist/lib/codex-manager/experimental-sync-target-entry.js +16 -0
  168. package/dist/lib/codex-manager/experimental-sync-target-entry.js.map +1 -0
  169. package/dist/lib/codex-manager/experimental-sync-target.d.ts +23 -0
  170. package/dist/lib/codex-manager/experimental-sync-target.d.ts.map +1 -0
  171. package/dist/lib/codex-manager/experimental-sync-target.js +39 -0
  172. package/dist/lib/codex-manager/experimental-sync-target.js.map +1 -0
  173. package/dist/lib/codex-manager/fix.d.ts +26 -0
  174. package/dist/lib/codex-manager/fix.d.ts.map +1 -0
  175. package/dist/lib/codex-manager/fix.js +366 -0
  176. package/dist/lib/codex-manager/fix.js.map +1 -0
  177. package/dist/lib/codex-manager/forecast-report-commands.d.ts +54 -0
  178. package/dist/lib/codex-manager/forecast-report-commands.d.ts.map +1 -0
  179. package/dist/lib/codex-manager/forecast-report-commands.js +443 -0
  180. package/dist/lib/codex-manager/forecast-report-commands.js.map +1 -0
  181. package/dist/lib/codex-manager/forecast.d.ts +26 -0
  182. package/dist/lib/codex-manager/forecast.d.ts.map +1 -0
  183. package/dist/lib/codex-manager/forecast.js +218 -0
  184. package/dist/lib/codex-manager/forecast.js.map +1 -0
  185. package/dist/lib/codex-manager/help.d.ts +36 -0
  186. package/dist/lib/codex-manager/help.d.ts.map +1 -0
  187. package/dist/lib/codex-manager/help.js +125 -0
  188. package/dist/lib/codex-manager/help.js.map +1 -0
  189. package/dist/lib/codex-manager/info.d.ts +11 -0
  190. package/dist/lib/codex-manager/info.d.ts.map +1 -0
  191. package/dist/lib/codex-manager/info.js +91 -0
  192. package/dist/lib/codex-manager/info.js.map +1 -0
  193. package/dist/lib/codex-manager/login.d.ts +40 -0
  194. package/dist/lib/codex-manager/login.d.ts.map +1 -0
  195. package/dist/lib/codex-manager/login.js +1041 -0
  196. package/dist/lib/codex-manager/login.js.map +1 -0
  197. package/dist/lib/codex-manager/repair-commands.d.ts +70 -0
  198. package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -0
  199. package/dist/lib/codex-manager/repair-commands.js +1671 -0
  200. package/dist/lib/codex-manager/repair-commands.js.map +1 -0
  201. package/dist/lib/codex-manager/report.d.ts +39 -0
  202. package/dist/lib/codex-manager/report.d.ts.map +1 -0
  203. package/dist/lib/codex-manager/report.js +243 -0
  204. package/dist/lib/codex-manager/report.js.map +1 -0
  205. package/dist/lib/codex-manager/settings-hub-entry.d.ts +30 -0
  206. package/dist/lib/codex-manager/settings-hub-entry.d.ts.map +1 -0
  207. package/dist/lib/codex-manager/settings-hub-entry.js +11 -0
  208. package/dist/lib/codex-manager/settings-hub-entry.js.map +1 -0
  209. package/dist/lib/codex-manager/settings-hub-menu.d.ts +30 -0
  210. package/dist/lib/codex-manager/settings-hub-menu.d.ts.map +1 -0
  211. package/dist/lib/codex-manager/settings-hub-menu.js +37 -0
  212. package/dist/lib/codex-manager/settings-hub-menu.js.map +1 -0
  213. package/dist/lib/codex-manager/settings-hub-prompt.d.ts +25 -0
  214. package/dist/lib/codex-manager/settings-hub-prompt.d.ts.map +1 -0
  215. package/dist/lib/codex-manager/settings-hub-prompt.js +23 -0
  216. package/dist/lib/codex-manager/settings-hub-prompt.js.map +1 -0
  217. package/dist/lib/codex-manager/settings-hub.d.ts +12 -10
  218. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  219. package/dist/lib/codex-manager/settings-hub.js +262 -2187
  220. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  221. package/dist/lib/codex-manager/settings-panels.d.ts +56 -0
  222. package/dist/lib/codex-manager/settings-panels.d.ts.map +1 -0
  223. package/dist/lib/codex-manager/settings-panels.js +73 -0
  224. package/dist/lib/codex-manager/settings-panels.js.map +1 -0
  225. package/dist/lib/codex-manager/settings-persist-utils.d.ts +9 -0
  226. package/dist/lib/codex-manager/settings-persist-utils.d.ts.map +1 -0
  227. package/dist/lib/codex-manager/settings-persist-utils.js +33 -0
  228. package/dist/lib/codex-manager/settings-persist-utils.js.map +1 -0
  229. package/dist/lib/codex-manager/settings-preview.d.ts +12 -0
  230. package/dist/lib/codex-manager/settings-preview.d.ts.map +1 -0
  231. package/dist/lib/codex-manager/settings-preview.js +118 -0
  232. package/dist/lib/codex-manager/settings-preview.js.map +1 -0
  233. package/dist/lib/codex-manager/settings-write-queue.d.ts +14 -0
  234. package/dist/lib/codex-manager/settings-write-queue.d.ts.map +1 -0
  235. package/dist/lib/codex-manager/settings-write-queue.js +88 -0
  236. package/dist/lib/codex-manager/settings-write-queue.js.map +1 -0
  237. package/dist/lib/codex-manager/statusline-order.d.ts +3 -0
  238. package/dist/lib/codex-manager/statusline-order.d.ts.map +1 -0
  239. package/dist/lib/codex-manager/statusline-order.js +17 -0
  240. package/dist/lib/codex-manager/statusline-order.js.map +1 -0
  241. package/dist/lib/codex-manager/statusline-settings-panel.d.ts +40 -0
  242. package/dist/lib/codex-manager/statusline-settings-panel.d.ts.map +1 -0
  243. package/dist/lib/codex-manager/statusline-settings-panel.js +167 -0
  244. package/dist/lib/codex-manager/statusline-settings-panel.js.map +1 -0
  245. package/dist/lib/codex-manager/switch.d.ts +31 -0
  246. package/dist/lib/codex-manager/switch.d.ts.map +1 -0
  247. package/dist/lib/codex-manager/switch.js +103 -0
  248. package/dist/lib/codex-manager/switch.js.map +1 -0
  249. package/dist/lib/codex-manager/theme-settings-panel.d.ts +26 -0
  250. package/dist/lib/codex-manager/theme-settings-panel.d.ts.map +1 -0
  251. package/dist/lib/codex-manager/theme-settings-panel.js +131 -0
  252. package/dist/lib/codex-manager/theme-settings-panel.js.map +1 -0
  253. package/dist/lib/codex-manager/unified-settings-controller.d.ts +27 -0
  254. package/dist/lib/codex-manager/unified-settings-controller.d.ts.map +1 -0
  255. package/dist/lib/codex-manager/unified-settings-controller.js +50 -0
  256. package/dist/lib/codex-manager/unified-settings-controller.js.map +1 -0
  257. package/dist/lib/codex-manager/unified-settings-entry.d.ts +6 -0
  258. package/dist/lib/codex-manager/unified-settings-entry.d.ts.map +1 -0
  259. package/dist/lib/codex-manager/unified-settings-entry.js +23 -0
  260. package/dist/lib/codex-manager/unified-settings-entry.js.map +1 -0
  261. package/dist/lib/codex-manager/verify-flagged.d.ts +20 -0
  262. package/dist/lib/codex-manager/verify-flagged.d.ts.map +1 -0
  263. package/dist/lib/codex-manager/verify-flagged.js +316 -0
  264. package/dist/lib/codex-manager/verify-flagged.js.map +1 -0
  265. package/dist/lib/codex-manager.d.ts +1 -0
  266. package/dist/lib/codex-manager.d.ts.map +1 -1
  267. package/dist/lib/codex-manager.js +767 -2195
  268. package/dist/lib/codex-manager.js.map +1 -1
  269. package/dist/lib/config.d.ts +38 -0
  270. package/dist/lib/config.d.ts.map +1 -1
  271. package/dist/lib/config.js +371 -9
  272. package/dist/lib/config.js.map +1 -1
  273. package/dist/lib/errors.d.ts +9 -0
  274. package/dist/lib/errors.d.ts.map +1 -1
  275. package/dist/lib/errors.js +13 -0
  276. package/dist/lib/errors.js.map +1 -1
  277. package/dist/lib/forecast.d.ts +17 -0
  278. package/dist/lib/forecast.d.ts.map +1 -1
  279. package/dist/lib/forecast.js +33 -6
  280. package/dist/lib/forecast.js.map +1 -1
  281. package/dist/lib/named-backup-export.js +2 -2
  282. package/dist/lib/named-backup-export.js.map +1 -1
  283. package/dist/lib/prompts/codex.d.ts +8 -3
  284. package/dist/lib/prompts/codex.d.ts.map +1 -1
  285. package/dist/lib/prompts/codex.js +16 -26
  286. package/dist/lib/prompts/codex.js.map +1 -1
  287. package/dist/lib/request/failover-config.d.ts +4 -0
  288. package/dist/lib/request/failover-config.d.ts.map +1 -0
  289. package/dist/lib/request/failover-config.js +15 -0
  290. package/dist/lib/request/failover-config.js.map +1 -0
  291. package/dist/lib/request/fetch-helpers.d.ts +28 -4
  292. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  293. package/dist/lib/request/fetch-helpers.js +170 -8
  294. package/dist/lib/request/fetch-helpers.js.map +1 -1
  295. package/dist/lib/request/helpers/model-map.d.ts +49 -12
  296. package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
  297. package/dist/lib/request/helpers/model-map.js +303 -108
  298. package/dist/lib/request/helpers/model-map.js.map +1 -1
  299. package/dist/lib/request/helpers/tool-utils.d.ts +2 -15
  300. package/dist/lib/request/helpers/tool-utils.d.ts.map +1 -1
  301. package/dist/lib/request/helpers/tool-utils.js +40 -27
  302. package/dist/lib/request/helpers/tool-utils.js.map +1 -1
  303. package/dist/lib/request/index.d.ts +5 -0
  304. package/dist/lib/request/index.d.ts.map +1 -0
  305. package/dist/lib/request/index.js +5 -0
  306. package/dist/lib/request/index.js.map +1 -0
  307. package/dist/lib/request/request-init.d.ts +3 -0
  308. package/dist/lib/request/request-init.d.ts.map +1 -0
  309. package/dist/lib/request/request-init.js +50 -0
  310. package/dist/lib/request/request-init.js.map +1 -0
  311. package/dist/lib/request/request-transformer.d.ts +19 -6
  312. package/dist/lib/request/request-transformer.d.ts.map +1 -1
  313. package/dist/lib/request/request-transformer.js +210 -193
  314. package/dist/lib/request/request-transformer.js.map +1 -1
  315. package/dist/lib/request/response-compaction.d.ts +20 -0
  316. package/dist/lib/request/response-compaction.d.ts.map +1 -0
  317. package/dist/lib/request/response-compaction.js +124 -0
  318. package/dist/lib/request/response-compaction.js.map +1 -0
  319. package/dist/lib/request/response-handler.d.ts +2 -0
  320. package/dist/lib/request/response-handler.d.ts.map +1 -1
  321. package/dist/lib/request/response-handler.js +567 -11
  322. package/dist/lib/request/response-handler.js.map +1 -1
  323. package/dist/lib/request/response-metadata.d.ts +3 -0
  324. package/dist/lib/request/response-metadata.d.ts.map +1 -0
  325. package/dist/lib/request/response-metadata.js +61 -0
  326. package/dist/lib/request/response-metadata.js.map +1 -0
  327. package/dist/lib/request/trace-mode.d.ts +9 -0
  328. package/dist/lib/request/trace-mode.d.ts.map +1 -0
  329. package/dist/lib/request/trace-mode.js +14 -0
  330. package/dist/lib/request/trace-mode.js.map +1 -0
  331. package/dist/lib/request/wait-utils.d.ts +14 -0
  332. package/dist/lib/request/wait-utils.d.ts.map +1 -0
  333. package/dist/lib/request/wait-utils.js +44 -0
  334. package/dist/lib/request/wait-utils.js.map +1 -0
  335. package/dist/lib/runtime/account-check-helpers.d.ts +8 -0
  336. package/dist/lib/runtime/account-check-helpers.d.ts.map +1 -0
  337. package/dist/lib/runtime/account-check-helpers.js +30 -0
  338. package/dist/lib/runtime/account-check-helpers.js.map +1 -0
  339. package/dist/lib/runtime/account-check-types.d.ts +18 -0
  340. package/dist/lib/runtime/account-check-types.d.ts.map +1 -0
  341. package/dist/lib/runtime/account-check-types.js +12 -0
  342. package/dist/lib/runtime/account-check-types.js.map +1 -0
  343. package/dist/lib/runtime/account-check.d.ts +48 -0
  344. package/dist/lib/runtime/account-check.d.ts.map +1 -0
  345. package/dist/lib/runtime/account-check.js +202 -0
  346. package/dist/lib/runtime/account-check.js.map +1 -0
  347. package/dist/lib/runtime/account-health-check.d.ts +8 -0
  348. package/dist/lib/runtime/account-health-check.d.ts.map +1 -0
  349. package/dist/lib/runtime/account-health-check.js +30 -0
  350. package/dist/lib/runtime/account-health-check.js.map +1 -0
  351. package/dist/lib/runtime/account-manager-cache-entry.d.ts +25 -0
  352. package/dist/lib/runtime/account-manager-cache-entry.d.ts.map +1 -0
  353. package/dist/lib/runtime/account-manager-cache-entry.js +17 -0
  354. package/dist/lib/runtime/account-manager-cache-entry.js.map +1 -0
  355. package/dist/lib/runtime/account-manager-cache.d.ts +25 -0
  356. package/dist/lib/runtime/account-manager-cache.d.ts.map +1 -0
  357. package/dist/lib/runtime/account-manager-cache.js +44 -0
  358. package/dist/lib/runtime/account-manager-cache.js.map +1 -0
  359. package/dist/lib/runtime/account-pool.d.ts +23 -0
  360. package/dist/lib/runtime/account-pool.d.ts.map +1 -0
  361. package/dist/lib/runtime/account-pool.js +138 -0
  362. package/dist/lib/runtime/account-pool.js.map +1 -0
  363. package/dist/lib/runtime/account-scope.d.ts +10 -0
  364. package/dist/lib/runtime/account-scope.d.ts.map +1 -0
  365. package/dist/lib/runtime/account-scope.js +13 -0
  366. package/dist/lib/runtime/account-scope.js.map +1 -0
  367. package/dist/lib/runtime/account-select-event.d.ts +19 -0
  368. package/dist/lib/runtime/account-select-event.d.ts.map +1 -0
  369. package/dist/lib/runtime/account-select-event.js +53 -0
  370. package/dist/lib/runtime/account-select-event.js.map +1 -0
  371. package/dist/lib/runtime/account-selection.d.ts +28 -0
  372. package/dist/lib/runtime/account-selection.d.ts.map +1 -0
  373. package/dist/lib/runtime/account-selection.js +46 -0
  374. package/dist/lib/runtime/account-selection.js.map +1 -0
  375. package/dist/lib/runtime/account-state.d.ts +13 -0
  376. package/dist/lib/runtime/account-state.d.ts.map +1 -0
  377. package/dist/lib/runtime/account-state.js +38 -0
  378. package/dist/lib/runtime/account-state.js.map +1 -0
  379. package/dist/lib/runtime/account-status.d.ts +13 -0
  380. package/dist/lib/runtime/account-status.d.ts.map +1 -0
  381. package/dist/lib/runtime/account-status.js +37 -0
  382. package/dist/lib/runtime/account-status.js.map +1 -0
  383. package/dist/lib/runtime/account-storage-scope-entry.d.ts +26 -0
  384. package/dist/lib/runtime/account-storage-scope-entry.d.ts.map +1 -0
  385. package/dist/lib/runtime/account-storage-scope-entry.js +15 -0
  386. package/dist/lib/runtime/account-storage-scope-entry.js.map +1 -0
  387. package/dist/lib/runtime/auth-facade.d.ts +51 -0
  388. package/dist/lib/runtime/auth-facade.d.ts.map +1 -0
  389. package/dist/lib/runtime/auth-facade.js +48 -0
  390. package/dist/lib/runtime/auth-facade.js.map +1 -0
  391. package/dist/lib/runtime/browser-oauth-flow.d.ts +32 -0
  392. package/dist/lib/runtime/browser-oauth-flow.d.ts.map +1 -0
  393. package/dist/lib/runtime/browser-oauth-flow.js +31 -0
  394. package/dist/lib/runtime/browser-oauth-flow.js.map +1 -0
  395. package/dist/lib/runtime/capability-boost.d.ts +25 -0
  396. package/dist/lib/runtime/capability-boost.d.ts.map +1 -0
  397. package/dist/lib/runtime/capability-boost.js +26 -0
  398. package/dist/lib/runtime/capability-boost.js.map +1 -0
  399. package/dist/lib/runtime/event-handler.d.ts +53 -0
  400. package/dist/lib/runtime/event-handler.d.ts.map +1 -0
  401. package/dist/lib/runtime/event-handler.js +46 -0
  402. package/dist/lib/runtime/event-handler.js.map +1 -0
  403. package/dist/lib/runtime/flagged-verify-types.d.ts +9 -0
  404. package/dist/lib/runtime/flagged-verify-types.d.ts.map +1 -0
  405. package/dist/lib/runtime/flagged-verify-types.js +7 -0
  406. package/dist/lib/runtime/flagged-verify-types.js.map +1 -0
  407. package/dist/lib/runtime/hydrate-emails.d.ts +13 -0
  408. package/dist/lib/runtime/hydrate-emails.d.ts.map +1 -0
  409. package/dist/lib/runtime/hydrate-emails.js +56 -0
  410. package/dist/lib/runtime/hydrate-emails.js.map +1 -0
  411. package/dist/lib/runtime/live-sync-entry.d.ts +36 -0
  412. package/dist/lib/runtime/live-sync-entry.d.ts.map +1 -0
  413. package/dist/lib/runtime/live-sync-entry.js +14 -0
  414. package/dist/lib/runtime/live-sync-entry.js.map +1 -0
  415. package/dist/lib/runtime/live-sync.d.ts +35 -0
  416. package/dist/lib/runtime/live-sync.d.ts.map +1 -0
  417. package/dist/lib/runtime/live-sync.js +65 -0
  418. package/dist/lib/runtime/live-sync.js.map +1 -0
  419. package/dist/lib/runtime/loader-setup.d.ts +9 -0
  420. package/dist/lib/runtime/loader-setup.d.ts.map +1 -0
  421. package/dist/lib/runtime/loader-setup.js +8 -0
  422. package/dist/lib/runtime/loader-setup.js.map +1 -0
  423. package/dist/lib/runtime/login-menu-accounts.d.ts +29 -0
  424. package/dist/lib/runtime/login-menu-accounts.d.ts.map +1 -0
  425. package/dist/lib/runtime/login-menu-accounts.js +33 -0
  426. package/dist/lib/runtime/login-menu-accounts.js.map +1 -0
  427. package/dist/lib/runtime/manual-oauth-flow.d.ts +40 -0
  428. package/dist/lib/runtime/manual-oauth-flow.d.ts.map +1 -0
  429. package/dist/lib/runtime/manual-oauth-flow.js +71 -0
  430. package/dist/lib/runtime/manual-oauth-flow.js.map +1 -0
  431. package/dist/lib/runtime/metrics.d.ts +29 -0
  432. package/dist/lib/runtime/metrics.d.ts.map +1 -0
  433. package/dist/lib/runtime/metrics.js +97 -0
  434. package/dist/lib/runtime/metrics.js.map +1 -0
  435. package/dist/lib/runtime/oauth-browser-flow.d.ts +9 -0
  436. package/dist/lib/runtime/oauth-browser-flow.d.ts.map +1 -0
  437. package/dist/lib/runtime/oauth-browser-flow.js +34 -0
  438. package/dist/lib/runtime/oauth-browser-flow.js.map +1 -0
  439. package/dist/lib/runtime/preemptive-quota.d.ts +13 -0
  440. package/dist/lib/runtime/preemptive-quota.d.ts.map +1 -0
  441. package/dist/lib/runtime/preemptive-quota.js +9 -0
  442. package/dist/lib/runtime/preemptive-quota.js.map +1 -0
  443. package/dist/lib/runtime/quota-headers.d.ts +12 -0
  444. package/dist/lib/runtime/quota-headers.d.ts.map +1 -0
  445. package/dist/lib/runtime/quota-headers.js +131 -0
  446. package/dist/lib/runtime/quota-headers.js.map +1 -0
  447. package/dist/lib/runtime/quota-probe.d.ts +18 -0
  448. package/dist/lib/runtime/quota-probe.d.ts.map +1 -0
  449. package/dist/lib/runtime/quota-probe.js +82 -0
  450. package/dist/lib/runtime/quota-probe.js.map +1 -0
  451. package/dist/lib/runtime/quota-settings.d.ts +14 -0
  452. package/dist/lib/runtime/quota-settings.d.ts.map +1 -0
  453. package/dist/lib/runtime/quota-settings.js +12 -0
  454. package/dist/lib/runtime/quota-settings.js.map +1 -0
  455. package/dist/lib/runtime/refresh-guardian-entry.d.ts +32 -0
  456. package/dist/lib/runtime/refresh-guardian-entry.d.ts.map +1 -0
  457. package/dist/lib/runtime/refresh-guardian-entry.js +12 -0
  458. package/dist/lib/runtime/refresh-guardian-entry.js.map +1 -0
  459. package/dist/lib/runtime/refresh-guardian.d.ts +24 -0
  460. package/dist/lib/runtime/refresh-guardian.d.ts.map +1 -0
  461. package/dist/lib/runtime/refresh-guardian.js +32 -0
  462. package/dist/lib/runtime/refresh-guardian.js.map +1 -0
  463. package/dist/lib/runtime/request-init.d.ts +5 -0
  464. package/dist/lib/runtime/request-init.d.ts.map +1 -0
  465. package/dist/lib/runtime/request-init.js +50 -0
  466. package/dist/lib/runtime/request-init.js.map +1 -0
  467. package/dist/lib/runtime/runtime-services.d.ts +58 -0
  468. package/dist/lib/runtime/runtime-services.d.ts.map +1 -0
  469. package/dist/lib/runtime/runtime-services.js +87 -0
  470. package/dist/lib/runtime/runtime-services.js.map +1 -0
  471. package/dist/lib/runtime/session-affinity-entry.d.ts +30 -0
  472. package/dist/lib/runtime/session-affinity-entry.d.ts.map +1 -0
  473. package/dist/lib/runtime/session-affinity-entry.js +11 -0
  474. package/dist/lib/runtime/session-affinity-entry.js.map +1 -0
  475. package/dist/lib/runtime/session-affinity.d.ts +13 -0
  476. package/dist/lib/runtime/session-affinity.d.ts.map +1 -0
  477. package/dist/lib/runtime/session-affinity.js +17 -0
  478. package/dist/lib/runtime/session-affinity.js.map +1 -0
  479. package/dist/lib/runtime/session-recovery.d.ts +8 -0
  480. package/dist/lib/runtime/session-recovery.d.ts.map +1 -0
  481. package/dist/lib/runtime/session-recovery.js +7 -0
  482. package/dist/lib/runtime/session-recovery.js.map +1 -0
  483. package/dist/lib/runtime/status-marker.d.ts +3 -0
  484. package/dist/lib/runtime/status-marker.d.ts.map +1 -0
  485. package/dist/lib/runtime/status-marker.js +15 -0
  486. package/dist/lib/runtime/status-marker.js.map +1 -0
  487. package/dist/lib/runtime/storage-scope.d.ts +13 -0
  488. package/dist/lib/runtime/storage-scope.d.ts.map +1 -0
  489. package/dist/lib/runtime/storage-scope.js +14 -0
  490. package/dist/lib/runtime/storage-scope.js.map +1 -0
  491. package/dist/lib/runtime/toast.d.ts +16 -0
  492. package/dist/lib/runtime/toast.d.ts.map +1 -0
  493. package/dist/lib/runtime/toast.js +16 -0
  494. package/dist/lib/runtime/toast.js.map +1 -0
  495. package/dist/lib/runtime/ui-runtime-entry.d.ts +7 -0
  496. package/dist/lib/runtime/ui-runtime-entry.d.ts.map +1 -0
  497. package/dist/lib/runtime/ui-runtime-entry.js +4 -0
  498. package/dist/lib/runtime/ui-runtime-entry.js.map +1 -0
  499. package/dist/lib/runtime/ui-runtime.d.ts +9 -0
  500. package/dist/lib/runtime/ui-runtime.d.ts.map +1 -0
  501. package/dist/lib/runtime/ui-runtime.js +23 -0
  502. package/dist/lib/runtime/ui-runtime.js.map +1 -0
  503. package/dist/lib/runtime/verify-flagged.d.ts +44 -0
  504. package/dist/lib/runtime/verify-flagged.d.ts.map +1 -0
  505. package/dist/lib/runtime/verify-flagged.js +84 -0
  506. package/dist/lib/runtime/verify-flagged.js.map +1 -0
  507. package/dist/lib/schemas.d.ts +9 -0
  508. package/dist/lib/schemas.d.ts.map +1 -1
  509. package/dist/lib/schemas.js +9 -1
  510. package/dist/lib/schemas.js.map +1 -1
  511. package/dist/lib/session-affinity.d.ts +10 -0
  512. package/dist/lib/session-affinity.d.ts.map +1 -1
  513. package/dist/lib/session-affinity.js +53 -6
  514. package/dist/lib/session-affinity.js.map +1 -1
  515. package/dist/lib/storage/account-clear-entry.d.ts +16 -0
  516. package/dist/lib/storage/account-clear-entry.d.ts.map +1 -0
  517. package/dist/lib/storage/account-clear-entry.js +12 -0
  518. package/dist/lib/storage/account-clear-entry.js.map +1 -0
  519. package/dist/lib/storage/account-clear.d.ts +8 -0
  520. package/dist/lib/storage/account-clear.d.ts.map +1 -0
  521. package/dist/lib/storage/account-clear.js +29 -0
  522. package/dist/lib/storage/account-clear.js.map +1 -0
  523. package/dist/lib/storage/account-match-utils.d.ts +9 -0
  524. package/dist/lib/storage/account-match-utils.d.ts.map +1 -0
  525. package/dist/lib/storage/account-match-utils.js +45 -0
  526. package/dist/lib/storage/account-match-utils.js.map +1 -0
  527. package/dist/lib/storage/account-persistence.d.ts +3 -0
  528. package/dist/lib/storage/account-persistence.d.ts.map +1 -0
  529. package/dist/lib/storage/account-persistence.js +12 -0
  530. package/dist/lib/storage/account-persistence.js.map +1 -0
  531. package/dist/lib/storage/account-port.d.ts +50 -0
  532. package/dist/lib/storage/account-port.d.ts.map +1 -0
  533. package/dist/lib/storage/account-port.js +43 -0
  534. package/dist/lib/storage/account-port.js.map +1 -0
  535. package/dist/lib/storage/account-save-entry.d.ts +7 -0
  536. package/dist/lib/storage/account-save-entry.d.ts.map +1 -0
  537. package/dist/lib/storage/account-save-entry.js +6 -0
  538. package/dist/lib/storage/account-save-entry.js.map +1 -0
  539. package/dist/lib/storage/account-save.d.ts +30 -0
  540. package/dist/lib/storage/account-save.d.ts.map +1 -0
  541. package/dist/lib/storage/account-save.js +49 -0
  542. package/dist/lib/storage/account-save.js.map +1 -0
  543. package/dist/lib/storage/account-snapshot.d.ts +25 -0
  544. package/dist/lib/storage/account-snapshot.d.ts.map +1 -0
  545. package/dist/lib/storage/account-snapshot.js +78 -0
  546. package/dist/lib/storage/account-snapshot.js.map +1 -0
  547. package/dist/lib/storage/backup-metadata-builder.d.ts +32 -0
  548. package/dist/lib/storage/backup-metadata-builder.d.ts.map +1 -0
  549. package/dist/lib/storage/backup-metadata-builder.js +77 -0
  550. package/dist/lib/storage/backup-metadata-builder.js.map +1 -0
  551. package/dist/lib/storage/backup-metadata.d.ts +29 -0
  552. package/dist/lib/storage/backup-metadata.d.ts.map +1 -0
  553. package/dist/lib/storage/backup-metadata.js +16 -0
  554. package/dist/lib/storage/backup-metadata.js.map +1 -0
  555. package/dist/lib/storage/backup-paths.d.ts +10 -0
  556. package/dist/lib/storage/backup-paths.d.ts.map +1 -0
  557. package/dist/lib/storage/backup-paths.js +27 -0
  558. package/dist/lib/storage/backup-paths.js.map +1 -0
  559. package/dist/lib/storage/backup-restore.d.ts +11 -0
  560. package/dist/lib/storage/backup-restore.d.ts.map +1 -0
  561. package/dist/lib/storage/backup-restore.js +52 -0
  562. package/dist/lib/storage/backup-restore.js.map +1 -0
  563. package/dist/lib/storage/cache-artifacts.d.ts +2 -0
  564. package/dist/lib/storage/cache-artifacts.d.ts.map +1 -0
  565. package/dist/lib/storage/cache-artifacts.js +4 -0
  566. package/dist/lib/storage/cache-artifacts.js.map +1 -0
  567. package/dist/lib/storage/error-hints.d.ts +10 -0
  568. package/dist/lib/storage/error-hints.d.ts.map +1 -0
  569. package/dist/lib/storage/error-hints.js +36 -0
  570. package/dist/lib/storage/error-hints.js.map +1 -0
  571. package/dist/lib/storage/file-paths.d.ts +6 -0
  572. package/dist/lib/storage/file-paths.d.ts.map +1 -0
  573. package/dist/lib/storage/file-paths.js +17 -0
  574. package/dist/lib/storage/file-paths.js.map +1 -0
  575. package/dist/lib/storage/fixture-guards.d.ts +4 -0
  576. package/dist/lib/storage/fixture-guards.d.ts.map +1 -0
  577. package/dist/lib/storage/fixture-guards.js +27 -0
  578. package/dist/lib/storage/fixture-guards.js.map +1 -0
  579. package/dist/lib/storage/flagged-entry.d.ts +15 -0
  580. package/dist/lib/storage/flagged-entry.d.ts.map +1 -0
  581. package/dist/lib/storage/flagged-entry.js +12 -0
  582. package/dist/lib/storage/flagged-entry.js.map +1 -0
  583. package/dist/lib/storage/flagged-load-entry.d.ts +20 -0
  584. package/dist/lib/storage/flagged-load-entry.d.ts.map +1 -0
  585. package/dist/lib/storage/flagged-load-entry.js +13 -0
  586. package/dist/lib/storage/flagged-load-entry.js.map +1 -0
  587. package/dist/lib/storage/flagged-save-entry.d.ts +7 -0
  588. package/dist/lib/storage/flagged-save-entry.d.ts.map +1 -0
  589. package/dist/lib/storage/flagged-save-entry.js +6 -0
  590. package/dist/lib/storage/flagged-save-entry.js.map +1 -0
  591. package/dist/lib/storage/flagged-storage-file.d.ts +7 -0
  592. package/dist/lib/storage/flagged-storage-file.d.ts.map +1 -0
  593. package/dist/lib/storage/flagged-storage-file.js +25 -0
  594. package/dist/lib/storage/flagged-storage-file.js.map +1 -0
  595. package/dist/lib/storage/flagged-storage-io.d.ts +28 -0
  596. package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -0
  597. package/dist/lib/storage/flagged-storage-io.js +135 -0
  598. package/dist/lib/storage/flagged-storage-io.js.map +1 -0
  599. package/dist/lib/storage/flagged-storage.d.ts +6 -0
  600. package/dist/lib/storage/flagged-storage.d.ts.map +1 -0
  601. package/dist/lib/storage/flagged-storage.js +90 -0
  602. package/dist/lib/storage/flagged-storage.js.map +1 -0
  603. package/dist/lib/storage/gitignore.d.ts +7 -0
  604. package/dist/lib/storage/gitignore.d.ts.map +1 -0
  605. package/dist/lib/storage/gitignore.js +34 -0
  606. package/dist/lib/storage/gitignore.js.map +1 -0
  607. package/dist/lib/storage/hash.d.ts +2 -0
  608. package/dist/lib/storage/hash.d.ts.map +1 -0
  609. package/dist/lib/storage/hash.js +5 -0
  610. package/dist/lib/storage/hash.js.map +1 -0
  611. package/dist/lib/storage/identity.d.ts +15 -0
  612. package/dist/lib/storage/identity.d.ts.map +1 -0
  613. package/dist/lib/storage/identity.js +48 -0
  614. package/dist/lib/storage/identity.js.map +1 -0
  615. package/dist/lib/storage/import-export.d.ts +24 -0
  616. package/dist/lib/storage/import-export.d.ts.map +1 -0
  617. package/dist/lib/storage/import-export.js +108 -0
  618. package/dist/lib/storage/import-export.js.map +1 -0
  619. package/dist/lib/storage/metadata-section.d.ts +16 -0
  620. package/dist/lib/storage/metadata-section.d.ts.map +1 -0
  621. package/dist/lib/storage/metadata-section.js +16 -0
  622. package/dist/lib/storage/metadata-section.js.map +1 -0
  623. package/dist/lib/storage/migrations.d.ts +5 -2
  624. package/dist/lib/storage/migrations.d.ts.map +1 -1
  625. package/dist/lib/storage/migrations.js.map +1 -1
  626. package/dist/lib/storage/named-backup-entry.d.ts +15 -0
  627. package/dist/lib/storage/named-backup-entry.d.ts.map +1 -0
  628. package/dist/lib/storage/named-backup-entry.js +7 -0
  629. package/dist/lib/storage/named-backup-entry.js.map +1 -0
  630. package/dist/lib/storage/named-backups-entry.d.ts +19 -0
  631. package/dist/lib/storage/named-backups-entry.d.ts.map +1 -0
  632. package/dist/lib/storage/named-backups-entry.js +7 -0
  633. package/dist/lib/storage/named-backups-entry.js.map +1 -0
  634. package/dist/lib/storage/named-backups.d.ts +15 -0
  635. package/dist/lib/storage/named-backups.d.ts.map +1 -0
  636. package/dist/lib/storage/named-backups.js +68 -0
  637. package/dist/lib/storage/named-backups.js.map +1 -0
  638. package/dist/lib/storage/path-state.d.ts +9 -0
  639. package/dist/lib/storage/path-state.d.ts.map +1 -0
  640. package/dist/lib/storage/path-state.js +20 -0
  641. package/dist/lib/storage/path-state.js.map +1 -0
  642. package/dist/lib/storage/project-migration.d.ts +10 -0
  643. package/dist/lib/storage/project-migration.d.ts.map +1 -0
  644. package/dist/lib/storage/project-migration.js +38 -0
  645. package/dist/lib/storage/project-migration.js.map +1 -0
  646. package/dist/lib/storage/record-utils.d.ts +3 -0
  647. package/dist/lib/storage/record-utils.d.ts.map +1 -0
  648. package/dist/lib/storage/record-utils.js +9 -0
  649. package/dist/lib/storage/record-utils.js.map +1 -0
  650. package/dist/lib/storage/restore-assessment.d.ts +7 -0
  651. package/dist/lib/storage/restore-assessment.d.ts.map +1 -0
  652. package/dist/lib/storage/restore-assessment.js +42 -0
  653. package/dist/lib/storage/restore-assessment.js.map +1 -0
  654. package/dist/lib/storage/restore-backup-entry.d.ts +24 -0
  655. package/dist/lib/storage/restore-backup-entry.d.ts.map +1 -0
  656. package/dist/lib/storage/restore-backup-entry.js +10 -0
  657. package/dist/lib/storage/restore-backup-entry.js.map +1 -0
  658. package/dist/lib/storage/restore-metadata.d.ts +10 -0
  659. package/dist/lib/storage/restore-metadata.d.ts.map +1 -0
  660. package/dist/lib/storage/restore-metadata.js +18 -0
  661. package/dist/lib/storage/restore-metadata.js.map +1 -0
  662. package/dist/lib/storage/restore.d.ts +14 -0
  663. package/dist/lib/storage/restore.d.ts.map +1 -0
  664. package/dist/lib/storage/restore.js +53 -0
  665. package/dist/lib/storage/restore.js.map +1 -0
  666. package/dist/lib/storage/snapshot-inspectors.d.ts +22 -0
  667. package/dist/lib/storage/snapshot-inspectors.d.ts.map +1 -0
  668. package/dist/lib/storage/snapshot-inspectors.js +95 -0
  669. package/dist/lib/storage/snapshot-inspectors.js.map +1 -0
  670. package/dist/lib/storage/storage-parser.d.ts +15 -0
  671. package/dist/lib/storage/storage-parser.d.ts.map +1 -0
  672. package/dist/lib/storage/storage-parser.js +16 -0
  673. package/dist/lib/storage/storage-parser.js.map +1 -0
  674. package/dist/lib/storage/transactions.d.ts +23 -0
  675. package/dist/lib/storage/transactions.d.ts.map +1 -0
  676. package/dist/lib/storage/transactions.js +64 -0
  677. package/dist/lib/storage/transactions.js.map +1 -0
  678. package/dist/lib/storage.d.ts +12 -41
  679. package/dist/lib/storage.d.ts.map +1 -1
  680. package/dist/lib/storage.js +527 -938
  681. package/dist/lib/storage.js.map +1 -1
  682. package/dist/lib/types.d.ts +80 -1
  683. package/dist/lib/types.d.ts.map +1 -1
  684. package/dist/lib/ui/copy.d.ts +24 -4
  685. package/dist/lib/ui/copy.d.ts.map +1 -1
  686. package/dist/lib/ui/copy.js +24 -4
  687. package/dist/lib/ui/copy.js.map +1 -1
  688. package/package.json +44 -6
  689. package/scripts/check-pack-budget-lib.js +114 -0
  690. package/scripts/check-pack-budget.mjs +10 -0
  691. package/scripts/codex-multi-auth.js +34 -10
  692. package/scripts/install-codex-auth-utils.js +54 -14
  693. package/scripts/install-codex-auth.js +62 -33
  694. package/scripts/update-vendor-provenance.mjs +96 -0
  695. package/scripts/verify-vendor-provenance.mjs +53 -0
@@ -1,157 +1,81 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import { createHash } from "node:crypto";
3
1
  import { existsSync, promises as fs } from "node:fs";
4
2
  import { basename, dirname, join } from "node:path";
5
3
  import { ACCOUNT_LIMITS } from "./constants.js";
4
+ import { StorageError } from "./errors.js";
6
5
  import { createLogger } from "./logger.js";
7
- import { exportNamedBackupFile, resolveNamedBackupPath, } from "./named-backup-export.js";
6
+ import { exportNamedBackupFile, getNamedBackupRoot, resolveNamedBackupPath, } from "./named-backup-export.js";
8
7
  import { MODEL_FAMILIES } from "./prompts/codex.js";
9
- import { AnyAccountStorageSchema, getValidationErrors } from "./schemas.js";
8
+ import { clearAccountStorageArtifacts } from "./storage/account-clear.js";
9
+ import { clearAccountsEntry } from "./storage/account-clear-entry.js";
10
+ import { collectDistinctIdentityValues, findNewestMatchingIndex as findNewestMatchingIndexByRef, selectNewestAccount, } from "./storage/account-match-utils.js";
11
+ import { cloneAccountStorageForPersistence } from "./storage/account-persistence.js";
12
+ import { describeAccountSnapshot as describeAccountSnapshotWithDeps, statSnapshot as statSnapshotWithDeps, } from "./storage/account-snapshot.js";
13
+ import { exportAccountsSnapshot, importAccountsSnapshot, } from "./storage/account-port.js";
14
+ import { saveAccountsToDisk } from "./storage/account-save.js";
15
+ import { saveAccountsEntry } from "./storage/account-save-entry.js";
16
+ import { buildBackupMetadata } from "./storage/backup-metadata-builder.js";
17
+ import { buildMetadataSection, } from "./storage/backup-metadata.js";
18
+ import { isCacheLikeBackupArtifactName } from "./storage/cache-artifacts.js";
19
+ import { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath, getAccountsBackupRecoveryCandidates, getAccountsWalPath, getIntentionalResetMarkerPath, RESET_MARKER_SUFFIX, } from "./storage/backup-paths.js";
20
+ import { restoreAccountsFromBackupPath } from "./storage/backup-restore.js";
21
+ import { looksLikeSyntheticFixtureStorage } from "./storage/fixture-guards.js";
22
+ import { loadFlaggedAccountsFromFile } from "./storage/flagged-storage-file.js";
23
+ import { clearFlaggedAccountsEntry } from "./storage/flagged-entry.js";
24
+ import { loadFlaggedAccountsEntry } from "./storage/flagged-load-entry.js";
25
+ import { saveFlaggedAccountsEntry } from "./storage/flagged-save-entry.js";
26
+ import { normalizeFlaggedStorage } from "./storage/flagged-storage.js";
27
+ import { clearFlaggedAccountsOnDisk, loadFlaggedAccountsState, saveFlaggedAccountsUnlockedToDisk, } from "./storage/flagged-storage-io.js";
28
+ import { computeSha256 } from "./storage/hash.js";
29
+ import { ensureCodexGitignoreEntry } from "./storage/gitignore.js";
30
+ import { exportAccountsToFile, mergeImportedAccounts, readImportFile, } from "./storage/import-export.js";
31
+ import { formatStorageErrorHint } from "./storage/error-hints.js";
32
+ export { StorageError } from "./errors.js";
33
+ export { formatStorageErrorHint, toStorageError } from "./storage/error-hints.js";
34
+ export { getAccountIdentityKey, normalizeEmailKey, } from "./storage/identity.js";
35
+ import { toAccountIdentityRef, } from "./storage/identity.js";
36
+ import { getFlaggedAccountsPath as buildFlaggedAccountsPath, getLegacyFlaggedAccountsPath as buildLegacyFlaggedAccountsPath, } from "./storage/file-paths.js";
10
37
  import { migrateV1ToV3, } from "./storage/migrations.js";
38
+ import { exportNamedBackupEntry } from "./storage/named-backup-entry.js";
39
+ import { collectNamedBackups, } from "./storage/named-backups.js";
40
+ import { getNamedBackupsEntry } from "./storage/named-backups-entry.js";
41
+ import { getStoragePathState, setStoragePathState, } from "./storage/path-state.js";
11
42
  import { findProjectRoot, getConfigDir, getProjectConfigDir, getProjectGlobalConfigDir, resolvePath, resolveProjectStorageIdentityRoot, } from "./storage/paths.js";
43
+ import { loadNormalizedStorageFromPath, mergeStorageForMigration, } from "./storage/project-migration.js";
44
+ import { clampIndex, isRecord } from "./storage/record-utils.js";
45
+ import { buildRestoreAssessment } from "./storage/restore-assessment.js";
46
+ import { restoreAccountsFromBackupEntry } from "./storage/restore-backup-entry.js";
47
+ import { createEmptyStorageWithRestoreMetadata as createEmptyStorageWithMetadata, withRestoreMetadata, } from "./storage/restore-metadata.js";
48
+ import { loadAccountsFromPath, parseAndNormalizeStorage, } from "./storage/storage-parser.js";
49
+ import { getTransactionSnapshotState, runInTransactionSnapshotContext, withAccountStorageTransaction as runWithAccountStorageTransaction, withStorageLock, } from "./storage/transactions.js";
12
50
  const log = createLogger("storage");
13
51
  const ACCOUNTS_FILE_NAME = "openai-codex-accounts.json";
14
52
  const FLAGGED_ACCOUNTS_FILE_NAME = "openai-codex-flagged-accounts.json";
15
53
  const LEGACY_FLAGGED_ACCOUNTS_FILE_NAME = "openai-codex-blocked-accounts.json";
16
- const ACCOUNTS_BACKUP_SUFFIX = ".bak";
17
- const ACCOUNTS_WAL_SUFFIX = ".wal";
18
54
  const ACCOUNTS_BACKUP_HISTORY_DEPTH = 3;
19
55
  const BACKUP_COPY_MAX_ATTEMPTS = 5;
20
56
  const BACKUP_COPY_BASE_DELAY_MS = 10;
21
- const RESET_MARKER_SUFFIX = ".reset-intent";
22
57
  let storageBackupEnabled = true;
23
58
  let lastAccountsSaveTimestamp = 0;
24
- /**
25
- * Custom error class for storage operations with platform-aware hints.
26
- */
27
- export class StorageError extends Error {
28
- code;
29
- path;
30
- hint;
31
- constructor(message, code, path, hint, cause) {
32
- super(message, { cause });
33
- this.name = "StorageError";
34
- this.code = code;
35
- this.path = path;
36
- this.hint = hint;
37
- }
38
- }
39
- /**
40
- * Generate platform-aware troubleshooting hint based on error code.
41
- */
42
- export function formatStorageErrorHint(error, path) {
43
- const err = error;
44
- const code = err?.code || "UNKNOWN";
45
- const isWindows = process.platform === "win32";
46
- switch (code) {
47
- case "EACCES":
48
- case "EPERM":
49
- return isWindows
50
- ? `Permission denied writing to ${path}. Check antivirus exclusions for this folder. Ensure you have write permissions.`
51
- : `Permission denied writing to ${path}. Check folder permissions. Try: chmod 755 ~/.codex`;
52
- case "EBUSY":
53
- return `File is locked at ${path}. The file may be open in another program. Close any editors or processes accessing it.`;
54
- case "ENOSPC":
55
- return `Disk is full. Free up space and try again. Path: ${path}`;
56
- case "EEMPTY":
57
- return `File written but is empty. This may indicate a disk or filesystem issue. Path: ${path}`;
58
- default:
59
- return isWindows
60
- ? `Failed to write to ${path}. Check folder permissions and ensure path contains no special characters.`
61
- : `Failed to write to ${path}. Check folder permissions and disk space.`;
62
- }
63
- }
64
- let storageMutex = Promise.resolve();
65
- const transactionSnapshotContext = new AsyncLocalStorage();
66
- function withStorageLock(fn) {
67
- const previousMutex = storageMutex;
68
- let releaseLock;
69
- storageMutex = new Promise((resolve) => {
70
- releaseLock = resolve;
71
- });
72
- return previousMutex.then(fn).finally(() => releaseLock());
73
- }
74
- function looksLikeSyntheticFixtureAccount(account) {
75
- const email = typeof account.email === "string" ? account.email.trim().toLowerCase() : "";
76
- const refreshToken = typeof account.refreshToken === "string"
77
- ? account.refreshToken.trim().toLowerCase()
78
- : "";
79
- const accountId = typeof account.accountId === "string"
80
- ? account.accountId.trim().toLowerCase()
81
- : "";
82
- if (!/^account\d+@example\.com$/.test(email)) {
83
- return false;
84
- }
85
- const hasSyntheticRefreshToken = refreshToken.startsWith("fake_refresh") ||
86
- /^fake_refresh_token_\d+(_for_testing_only)?$/.test(refreshToken);
87
- if (!hasSyntheticRefreshToken) {
88
- return false;
89
- }
90
- if (accountId.length === 0) {
91
- return true;
92
- }
93
- return /^acc(_|-)?\d+$/.test(accountId);
94
- }
95
- function looksLikeSyntheticFixtureStorage(storage) {
96
- if (!storage || storage.accounts.length === 0)
97
- return false;
98
- return storage.accounts.every((account) => looksLikeSyntheticFixtureAccount(account));
99
- }
100
59
  async function ensureGitignore(storagePath) {
101
- if (!currentStoragePath)
60
+ const state = getStoragePathState();
61
+ if (!state.currentStoragePath)
102
62
  return;
103
- const configDir = dirname(storagePath);
104
- const inferredProjectRoot = dirname(configDir);
105
- const candidateRoots = [currentProjectRoot, inferredProjectRoot].filter((root) => typeof root === "string" && root.length > 0);
106
- const projectRoot = candidateRoots.find((root) => existsSync(join(root, ".git")));
107
- if (!projectRoot)
108
- return;
109
- const gitignorePath = join(projectRoot, ".gitignore");
110
- try {
111
- let content = "";
112
- if (existsSync(gitignorePath)) {
113
- content = await fs.readFile(gitignorePath, "utf-8");
114
- const lines = content.split("\n").map((l) => l.trim());
115
- if (lines.includes(".codex") ||
116
- lines.includes(".codex/") ||
117
- lines.includes("/.codex") ||
118
- lines.includes("/.codex/")) {
119
- return;
120
- }
121
- }
122
- const newContent = content.endsWith("\n") || content === "" ? content : content + "\n";
123
- await fs.writeFile(gitignorePath, newContent + ".codex/\n", "utf-8");
124
- log.debug("Added .codex to .gitignore", { path: gitignorePath });
125
- }
126
- catch (error) {
127
- log.warn("Failed to update .gitignore", { error: String(error) });
128
- }
63
+ await ensureCodexGitignoreEntry({
64
+ storagePath,
65
+ currentProjectRoot: state.currentProjectRoot,
66
+ logDebug: (message, details) => {
67
+ log.debug(message, details);
68
+ },
69
+ logWarn: (message, details) => {
70
+ log.warn(message, details);
71
+ },
72
+ });
129
73
  }
130
- let currentStoragePath = null;
131
- let currentLegacyProjectStoragePath = null;
132
- let currentLegacyWorktreeStoragePath = null;
133
- let currentProjectRoot = null;
134
74
  export function setStorageBackupEnabled(enabled) {
135
75
  storageBackupEnabled = enabled;
136
76
  }
137
- function getAccountsBackupPath(path) {
138
- return `${path}${ACCOUNTS_BACKUP_SUFFIX}`;
139
- }
140
- function getAccountsBackupPathAtIndex(path, index) {
141
- if (index <= 0) {
142
- return getAccountsBackupPath(path);
143
- }
144
- return `${path}${ACCOUNTS_BACKUP_SUFFIX}.${index}`;
145
- }
146
- function getAccountsBackupRecoveryCandidates(path) {
147
- const candidates = [];
148
- for (let i = 0; i < ACCOUNTS_BACKUP_HISTORY_DEPTH; i += 1) {
149
- candidates.push(getAccountsBackupPathAtIndex(path, i));
150
- }
151
- return candidates;
152
- }
153
77
  async function getAccountsBackupRecoveryCandidatesWithDiscovery(path) {
154
- const knownCandidates = getAccountsBackupRecoveryCandidates(path);
78
+ const knownCandidates = getAccountsBackupRecoveryCandidates(path, ACCOUNTS_BACKUP_HISTORY_DEPTH);
155
79
  const discoveredCandidates = new Set();
156
80
  const candidatePrefix = `${basename(path)}.`;
157
81
  const knownCandidateSet = new Set(knownCandidates);
@@ -191,9 +115,6 @@ async function getAccountsBackupRecoveryCandidatesWithDiscovery(path) {
191
115
  const discoveredOrdered = Array.from(discoveredCandidates).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
192
116
  return [...knownCandidates, ...discoveredOrdered];
193
117
  }
194
- function getAccountsWalPath(path) {
195
- return `${path}${ACCOUNTS_WAL_SUFFIX}`;
196
- }
197
118
  async function copyFileWithRetry(sourcePath, destinationPath, options) {
198
119
  const allowMissingSource = options?.allowMissingSource ?? false;
199
120
  for (let attempt = 0; attempt < BACKUP_COPY_MAX_ATTEMPTS; attempt += 1) {
@@ -235,7 +156,7 @@ async function renameFileWithRetry(sourcePath, destinationPath) {
235
156
  }
236
157
  }
237
158
  async function createRotatingAccountsBackup(path) {
238
- const candidates = getAccountsBackupRecoveryCandidates(path);
159
+ const candidates = getAccountsBackupRecoveryCandidates(path, ACCOUNTS_BACKUP_HISTORY_DEPTH);
239
160
  const rotationNonce = `${Date.now()}.${Math.random().toString(36).slice(2, 8)}`;
240
161
  const stagedWrites = [];
241
162
  const buildStagedPath = (targetPath, label) => `${targetPath}.rotate.${rotationNonce}.${label}.tmp`;
@@ -336,86 +257,22 @@ async function cleanupStaleRotatingBackupArtifacts(path) {
336
257
  }
337
258
  }
338
259
  }
339
- function computeSha256(value) {
340
- return createHash("sha256").update(value).digest("hex");
341
- }
342
- function getIntentionalResetMarkerPath(path) {
343
- return `${path}${RESET_MARKER_SUFFIX}`;
344
- }
345
- function createEmptyStorageWithMetadata(restoreEligible, restoreReason) {
346
- return {
347
- version: 3,
348
- accounts: [],
349
- activeIndex: 0,
350
- activeIndexByFamily: {},
351
- restoreEligible,
352
- restoreReason,
353
- };
354
- }
355
- function withRestoreMetadata(storage, restoreEligible, restoreReason) {
356
- return {
357
- ...storage,
358
- restoreEligible,
359
- restoreReason,
360
- };
361
- }
362
- function isCacheLikeBackupArtifactName(entryName) {
363
- return entryName.toLowerCase().includes(".cache");
364
- }
365
260
  async function statSnapshot(path) {
366
- try {
367
- const stats = await fs.stat(path);
368
- return { exists: true, bytes: stats.size, mtimeMs: stats.mtimeMs };
369
- }
370
- catch (error) {
371
- const code = error.code;
372
- if (code !== "ENOENT") {
373
- log.warn("Failed to stat backup candidate", {
374
- path,
375
- error: String(error),
376
- });
377
- }
378
- return { exists: false };
379
- }
261
+ return statSnapshotWithDeps(path, {
262
+ stat: fs.stat,
263
+ logWarn: (message, meta) => log.warn(message, meta),
264
+ });
380
265
  }
381
266
  async function describeAccountSnapshot(path, kind, index) {
382
- const stats = await statSnapshot(path);
383
- if (!stats.exists) {
384
- return { kind, path, index, exists: false, valid: false };
385
- }
386
- try {
387
- const { normalized, schemaErrors, storedVersion } = await loadAccountsFromPath(path);
388
- return {
389
- kind,
390
- path,
391
- index,
392
- exists: true,
393
- valid: !!normalized,
394
- bytes: stats.bytes,
395
- mtimeMs: stats.mtimeMs,
396
- version: typeof storedVersion === "number" ? storedVersion : undefined,
397
- accountCount: normalized?.accounts.length,
398
- schemaErrors: schemaErrors.length > 0 ? schemaErrors : undefined,
399
- };
400
- }
401
- catch (error) {
402
- const code = error.code;
403
- if (code !== "ENOENT") {
404
- log.warn("Failed to inspect account snapshot", {
405
- path,
406
- error: String(error),
407
- });
408
- }
409
- return {
410
- kind,
411
- path,
412
- index,
413
- exists: true,
414
- valid: false,
415
- bytes: stats.bytes,
416
- mtimeMs: stats.mtimeMs,
417
- };
418
- }
267
+ return describeAccountSnapshotWithDeps(path, kind, {
268
+ index,
269
+ statSnapshot,
270
+ loadAccountsFromPath: (targetPath) => loadAccountsFromPath(targetPath, {
271
+ normalizeAccountStorage,
272
+ isRecord,
273
+ }),
274
+ logWarn: (message, meta) => log.warn(message, meta),
275
+ });
419
276
  }
420
277
  async function describeAccountsWalSnapshot(path) {
421
278
  const stats = await statSnapshot(path);
@@ -449,7 +306,7 @@ async function describeAccountsWalSnapshot(path) {
449
306
  mtimeMs: stats.mtimeMs,
450
307
  };
451
308
  }
452
- const { normalized, storedVersion, schemaErrors } = parseAndNormalizeStorage(JSON.parse(entry.content));
309
+ const { normalized, storedVersion, schemaErrors } = parseAndNormalizeStorage(JSON.parse(entry.content), normalizeAccountStorage, isRecord);
453
310
  return {
454
311
  kind: "accounts-wal",
455
312
  path,
@@ -474,9 +331,13 @@ async function describeAccountsWalSnapshot(path) {
474
331
  }
475
332
  }
476
333
  async function loadFlaggedAccountsFromPath(path) {
477
- const content = await fs.readFile(path, "utf-8");
478
- const data = JSON.parse(content);
479
- return normalizeFlaggedStorage(data);
334
+ return loadFlaggedAccountsFromFile(path, {
335
+ readFile: fs.readFile,
336
+ normalizeFlaggedStorage: (data) => normalizeFlaggedStorage(data, {
337
+ isRecord,
338
+ now: () => Date.now(),
339
+ }),
340
+ });
480
341
  }
481
342
  async function describeFlaggedSnapshot(path, kind, index) {
482
343
  const stats = await statSnapshot(path);
@@ -516,93 +377,124 @@ async function describeFlaggedSnapshot(path, kind, index) {
516
377
  };
517
378
  }
518
379
  }
519
- function latestValidSnapshot(snapshots) {
520
- return snapshots
521
- .filter((snapshot) => snapshot.valid)
522
- .sort((left, right) => (right.mtimeMs ?? 0) - (left.mtimeMs ?? 0))[0];
523
- }
524
- function buildMetadataSection(storagePath, snapshots) {
525
- const latestValid = latestValidSnapshot(snapshots);
526
- return {
527
- storagePath,
528
- latestValidPath: latestValid?.path,
529
- snapshotCount: snapshots.length,
530
- validSnapshotCount: snapshots.filter((snapshot) => snapshot.valid).length,
531
- snapshots,
532
- };
533
- }
534
380
  export function getLastAccountsSaveTimestamp() {
535
381
  return lastAccountsSaveTimestamp;
536
382
  }
537
383
  export function setStoragePath(projectPath) {
538
384
  if (!projectPath) {
539
- currentStoragePath = null;
540
- currentLegacyProjectStoragePath = null;
541
- currentLegacyWorktreeStoragePath = null;
542
- currentProjectRoot = null;
385
+ setStoragePathState({
386
+ currentStoragePath: null,
387
+ currentLegacyProjectStoragePath: null,
388
+ currentLegacyWorktreeStoragePath: null,
389
+ currentProjectRoot: null,
390
+ });
543
391
  return;
544
392
  }
545
393
  const projectRoot = findProjectRoot(projectPath);
546
394
  if (projectRoot) {
547
- currentProjectRoot = projectRoot;
548
395
  const identityRoot = resolveProjectStorageIdentityRoot(projectRoot);
549
- currentStoragePath = join(getProjectGlobalConfigDir(identityRoot), ACCOUNTS_FILE_NAME);
550
- currentLegacyProjectStoragePath = join(getProjectConfigDir(projectRoot), ACCOUNTS_FILE_NAME);
396
+ const currentStoragePath = join(getProjectGlobalConfigDir(identityRoot), ACCOUNTS_FILE_NAME);
397
+ const currentLegacyProjectStoragePath = join(getProjectConfigDir(projectRoot), ACCOUNTS_FILE_NAME);
551
398
  const previousWorktreeScopedPath = join(getProjectGlobalConfigDir(projectRoot), ACCOUNTS_FILE_NAME);
552
- currentLegacyWorktreeStoragePath =
553
- previousWorktreeScopedPath !== currentStoragePath
554
- ? previousWorktreeScopedPath
555
- : null;
399
+ const currentLegacyWorktreeStoragePath = previousWorktreeScopedPath !== currentStoragePath
400
+ ? previousWorktreeScopedPath
401
+ : null;
402
+ setStoragePathState({
403
+ currentStoragePath,
404
+ currentLegacyProjectStoragePath,
405
+ currentLegacyWorktreeStoragePath,
406
+ currentProjectRoot: projectRoot,
407
+ });
556
408
  }
557
409
  else {
558
- currentStoragePath = null;
559
- currentLegacyProjectStoragePath = null;
560
- currentLegacyWorktreeStoragePath = null;
561
- currentProjectRoot = null;
410
+ setStoragePathState({
411
+ currentStoragePath: null,
412
+ currentLegacyProjectStoragePath: null,
413
+ currentLegacyWorktreeStoragePath: null,
414
+ currentProjectRoot: null,
415
+ });
562
416
  }
563
417
  }
564
418
  export function setStoragePathDirect(path) {
565
- currentStoragePath = path;
566
- currentLegacyProjectStoragePath = null;
567
- currentLegacyWorktreeStoragePath = null;
568
- currentProjectRoot = null;
419
+ setStoragePathState({
420
+ currentStoragePath: path,
421
+ currentLegacyProjectStoragePath: null,
422
+ currentLegacyWorktreeStoragePath: null,
423
+ currentProjectRoot: null,
424
+ });
569
425
  }
570
426
  /**
571
427
  * Returns the file path for the account storage JSON file.
572
428
  * @returns Absolute path to the accounts.json file
573
429
  */
574
430
  export function getStoragePath() {
575
- if (currentStoragePath) {
576
- return currentStoragePath;
431
+ const state = getStoragePathState();
432
+ if (state.currentStoragePath) {
433
+ return state.currentStoragePath;
577
434
  }
578
435
  return join(getConfigDir(), ACCOUNTS_FILE_NAME);
579
436
  }
580
437
  export function buildNamedBackupPath(name) {
581
438
  return resolveNamedBackupPath(name, getStoragePath());
582
439
  }
440
+ export async function getNamedBackups() {
441
+ return getNamedBackupsEntry({
442
+ getStoragePath,
443
+ collectNamedBackups,
444
+ loadAccountsFromPath: (path) => loadAccountsFromPath(path, {
445
+ normalizeAccountStorage,
446
+ isRecord,
447
+ }),
448
+ logDebug: (message, details) => {
449
+ log.debug(message, details);
450
+ },
451
+ });
452
+ }
453
+ export async function restoreAccountsFromBackup(path, options) {
454
+ return restoreAccountsFromBackupEntry({
455
+ path,
456
+ options,
457
+ restoreAccountsFromBackupPath,
458
+ getNamedBackupRoot,
459
+ getStoragePath,
460
+ realpath: fs.realpath,
461
+ loadAccountsFromPath: (path) => loadAccountsFromPath(path, {
462
+ normalizeAccountStorage,
463
+ isRecord,
464
+ }),
465
+ saveAccounts,
466
+ });
467
+ }
583
468
  export async function exportNamedBackup(name, options) {
584
- return exportNamedBackupFile(name, {
469
+ return exportNamedBackupEntry({
470
+ name,
471
+ options,
472
+ exportNamedBackupFile,
585
473
  getStoragePath,
586
474
  exportAccounts,
587
- }, options);
475
+ });
588
476
  }
589
477
  export function getFlaggedAccountsPath() {
590
- return join(dirname(getStoragePath()), FLAGGED_ACCOUNTS_FILE_NAME);
478
+ return buildFlaggedAccountsPath(getStoragePath(), FLAGGED_ACCOUNTS_FILE_NAME);
591
479
  }
592
480
  function getLegacyFlaggedAccountsPath() {
593
- return join(dirname(getStoragePath()), LEGACY_FLAGGED_ACCOUNTS_FILE_NAME);
481
+ return buildLegacyFlaggedAccountsPath(getStoragePath(), LEGACY_FLAGGED_ACCOUNTS_FILE_NAME);
594
482
  }
595
- async function migrateLegacyProjectStorageIfNeeded(persist = saveAccounts) {
596
- if (!currentStoragePath) {
483
+ async function migrateLegacyProjectStorageIfNeeded(options) {
484
+ const persist = options?.persist ?? saveAccounts;
485
+ const commit = options?.commit ?? true;
486
+ const state = getStoragePathState();
487
+ if (!state.currentStoragePath) {
597
488
  return null;
598
489
  }
490
+ const currentStoragePath = state.currentStoragePath;
599
491
  const candidatePaths = [
600
- currentLegacyWorktreeStoragePath,
601
- currentLegacyProjectStoragePath,
492
+ state.currentLegacyWorktreeStoragePath,
493
+ state.currentLegacyProjectStoragePath,
602
494
  ]
603
495
  .filter((path) => typeof path === "string" &&
604
496
  path.length > 0 &&
605
- path !== currentStoragePath)
497
+ path !== state.currentStoragePath)
606
498
  .filter((path, index, all) => all.indexOf(path) === index);
607
499
  if (candidatePaths.length === 0) {
608
500
  return null;
@@ -611,49 +503,106 @@ async function migrateLegacyProjectStorageIfNeeded(persist = saveAccounts) {
611
503
  if (existingCandidatePaths.length === 0) {
612
504
  return null;
613
505
  }
614
- let targetStorage = await loadNormalizedStorageFromPath(currentStoragePath, "current account storage");
615
- let migrated = false;
616
- for (const legacyPath of existingCandidatePaths) {
617
- const legacyStorage = await loadNormalizedStorageFromPath(legacyPath, "legacy account storage");
618
- if (!legacyStorage) {
619
- continue;
506
+ const loadCurrentStorageForMigration = async () => loadNormalizedStorageFromPath(currentStoragePath, "current account storage", {
507
+ loadAccountsFromPath: (path) => loadAccountsFromPath(path, {
508
+ normalizeAccountStorage,
509
+ isRecord,
510
+ }),
511
+ logWarn: (message, details) => {
512
+ log.warn(message, details);
513
+ },
514
+ });
515
+ const readLiveCurrentStorageIfExportMode = async () => {
516
+ if (commit || !existsSync(currentStoragePath)) {
517
+ return { exists: false, storage: null };
620
518
  }
621
- const mergedStorage = mergeStorageForMigration(targetStorage, legacyStorage);
622
- const fallbackStorage = targetStorage ?? legacyStorage;
623
519
  try {
624
- await persist(mergedStorage);
625
- targetStorage = mergedStorage;
626
- migrated = true;
520
+ const { normalized, schemaErrors } = await loadAccountsFromPath(currentStoragePath, {
521
+ normalizeAccountStorage,
522
+ isRecord,
523
+ });
524
+ if (schemaErrors.length > 0) {
525
+ log.warn("current account storage schema validation warnings", {
526
+ path: currentStoragePath,
527
+ errors: schemaErrors.slice(0, 5),
528
+ });
529
+ }
530
+ return {
531
+ exists: true,
532
+ storage: normalized,
533
+ };
627
534
  }
628
535
  catch (error) {
629
- targetStorage = fallbackStorage;
630
- log.warn("Failed to persist migrated account storage", {
631
- from: legacyPath,
632
- to: currentStoragePath,
633
- error: String(error),
634
- });
536
+ if (error.code === "ENOENT") {
537
+ return { exists: false, storage: null };
538
+ }
539
+ throw error;
540
+ }
541
+ };
542
+ let targetStorage = await loadCurrentStorageForMigration();
543
+ let migrated = false;
544
+ for (const legacyPath of existingCandidatePaths) {
545
+ const liveCurrentStorageBeforeMerge = await readLiveCurrentStorageIfExportMode();
546
+ if (liveCurrentStorageBeforeMerge.exists) {
547
+ return liveCurrentStorageBeforeMerge.storage;
548
+ }
549
+ const legacyStorage = await loadNormalizedStorageFromPath(legacyPath, "legacy account storage", {
550
+ loadAccountsFromPath: (path) => loadAccountsFromPath(path, {
551
+ normalizeAccountStorage,
552
+ isRecord,
553
+ }),
554
+ logWarn: (message, details) => {
555
+ log.warn(message, details);
556
+ },
557
+ });
558
+ if (!legacyStorage) {
635
559
  continue;
636
560
  }
637
- try {
638
- await fs.unlink(legacyPath);
639
- log.info("Removed legacy account storage file after migration", {
640
- path: legacyPath,
641
- });
561
+ const liveCurrentStorageAfterLegacyRead = await readLiveCurrentStorageIfExportMode();
562
+ if (liveCurrentStorageAfterLegacyRead.exists) {
563
+ return liveCurrentStorageAfterLegacyRead.storage;
642
564
  }
643
- catch (unlinkError) {
644
- const code = unlinkError.code;
645
- if (code !== "ENOENT") {
646
- log.warn("Failed to remove legacy account storage file after migration", {
565
+ const mergedStorage = mergeStorageForMigration(targetStorage, legacyStorage, normalizeAccountStorage);
566
+ const fallbackStorage = targetStorage ?? legacyStorage;
567
+ if (commit) {
568
+ try {
569
+ await persist(mergedStorage);
570
+ targetStorage = mergedStorage;
571
+ migrated = true;
572
+ }
573
+ catch (error) {
574
+ targetStorage = fallbackStorage;
575
+ log.warn("Failed to persist migrated account storage", {
576
+ from: legacyPath,
577
+ to: currentStoragePath,
578
+ error: String(error),
579
+ });
580
+ continue;
581
+ }
582
+ try {
583
+ await fs.unlink(legacyPath);
584
+ log.info("Removed legacy account storage file after migration", {
647
585
  path: legacyPath,
648
- error: String(unlinkError),
649
586
  });
650
587
  }
588
+ catch (unlinkError) {
589
+ const code = unlinkError.code;
590
+ if (code !== "ENOENT") {
591
+ log.warn("Failed to remove legacy account storage file after migration", {
592
+ path: legacyPath,
593
+ error: String(unlinkError),
594
+ });
595
+ }
596
+ }
597
+ log.info("Migrated legacy project account storage", {
598
+ from: legacyPath,
599
+ to: currentStoragePath,
600
+ accounts: mergedStorage.accounts.length,
601
+ });
602
+ continue;
651
603
  }
652
- log.info("Migrated legacy project account storage", {
653
- from: legacyPath,
654
- to: currentStoragePath,
655
- accounts: mergedStorage.accounts.length,
656
- });
604
+ targetStorage = mergedStorage;
605
+ migrated = true;
657
606
  }
658
607
  if (migrated) {
659
608
  return targetStorage;
@@ -663,129 +612,8 @@ async function migrateLegacyProjectStorageIfNeeded(persist = saveAccounts) {
663
612
  }
664
613
  return null;
665
614
  }
666
- async function loadNormalizedStorageFromPath(path, label) {
667
- try {
668
- const { normalized, schemaErrors } = await loadAccountsFromPath(path);
669
- if (schemaErrors.length > 0) {
670
- log.warn(`${label} schema validation warnings`, {
671
- path,
672
- errors: schemaErrors.slice(0, 5),
673
- });
674
- }
675
- return normalized;
676
- }
677
- catch (error) {
678
- const code = error.code;
679
- if (code !== "ENOENT") {
680
- log.warn(`Failed to load ${label}`, {
681
- path,
682
- error: String(error),
683
- });
684
- }
685
- return null;
686
- }
687
- }
688
- function mergeStorageForMigration(current, incoming) {
689
- if (!current) {
690
- return incoming;
691
- }
692
- const merged = normalizeAccountStorage({
693
- version: 3,
694
- activeIndex: current.activeIndex,
695
- activeIndexByFamily: current.activeIndexByFamily,
696
- accounts: [...current.accounts, ...incoming.accounts],
697
- });
698
- if (!merged) {
699
- return current;
700
- }
701
- return merged;
702
- }
703
- function selectNewestAccount(current, candidate) {
704
- if (!current)
705
- return candidate;
706
- const currentLastUsed = current.lastUsed || 0;
707
- const candidateLastUsed = candidate.lastUsed || 0;
708
- if (candidateLastUsed > currentLastUsed)
709
- return candidate;
710
- if (candidateLastUsed < currentLastUsed)
711
- return current;
712
- const currentAddedAt = current.addedAt || 0;
713
- const candidateAddedAt = candidate.addedAt || 0;
714
- return candidateAddedAt >= currentAddedAt ? candidate : current;
715
- }
716
- function normalizeAccountIdKey(accountId) {
717
- if (!accountId)
718
- return undefined;
719
- const trimmed = accountId.trim();
720
- return trimmed || undefined;
721
- }
722
- /**
723
- * Normalize email keys for case-insensitive account identity matching.
724
- */
725
- export function normalizeEmailKey(email) {
726
- if (!email)
727
- return undefined;
728
- const trimmed = email.trim();
729
- if (!trimmed)
730
- return undefined;
731
- return trimmed.toLowerCase();
732
- }
733
- function normalizeRefreshTokenKey(refreshToken) {
734
- if (!refreshToken)
735
- return undefined;
736
- const trimmed = refreshToken.trim();
737
- return trimmed || undefined;
738
- }
739
- function toAccountIdentityRef(account) {
740
- return {
741
- accountId: normalizeAccountIdKey(account?.accountId),
742
- emailKey: normalizeEmailKey(account?.email),
743
- refreshToken: normalizeRefreshTokenKey(account?.refreshToken),
744
- };
745
- }
746
- function collectDistinctIdentityValues(values) {
747
- const distinct = new Set();
748
- for (const value of values) {
749
- if (value)
750
- distinct.add(value);
751
- }
752
- return distinct;
753
- }
754
- export function getAccountIdentityKey(account) {
755
- const ref = toAccountIdentityRef(account);
756
- if (ref.accountId && ref.emailKey) {
757
- return `account:${ref.accountId}::email:${ref.emailKey}`;
758
- }
759
- if (ref.accountId)
760
- return `account:${ref.accountId}`;
761
- if (ref.emailKey)
762
- return `email:${ref.emailKey}`;
763
- if (ref.refreshToken)
764
- return `refresh:${ref.refreshToken}`;
765
- return undefined;
766
- }
767
615
  function findNewestMatchingIndex(accounts, predicate) {
768
- let matchIndex;
769
- let match;
770
- for (let i = 0; i < accounts.length; i += 1) {
771
- const account = accounts[i];
772
- if (!account)
773
- continue;
774
- const ref = toAccountIdentityRef(account);
775
- if (!predicate(ref))
776
- continue;
777
- if (matchIndex === undefined) {
778
- matchIndex = i;
779
- match = account;
780
- continue;
781
- }
782
- const newest = selectNewestAccount(match, account);
783
- if (newest === account) {
784
- matchIndex = i;
785
- match = account;
786
- }
787
- }
788
- return matchIndex;
616
+ return findNewestMatchingIndexByRef(accounts, (account) => toAccountIdentityRef(account), predicate, selectNewestAccount);
789
617
  }
790
618
  function findCompositeAccountMatchIndex(accounts, candidateRef) {
791
619
  if (!candidateRef.accountId || !candidateRef.emailKey)
@@ -932,14 +760,6 @@ export function deduplicateAccounts(accounts) {
932
760
  export function deduplicateAccountsByEmail(accounts) {
933
761
  return deduplicateAccountsByIdentity(accounts);
934
762
  }
935
- function isRecord(value) {
936
- return !!value && typeof value === "object" && !Array.isArray(value);
937
- }
938
- function clampIndex(index, length) {
939
- if (length <= 0)
940
- return 0;
941
- return Math.max(0, Math.min(index, length - 1));
942
- }
943
763
  function extractActiveAccountRef(accounts, activeIndex) {
944
764
  const candidate = accounts[activeIndex];
945
765
  if (!isRecord(candidate))
@@ -1030,92 +850,27 @@ export async function loadAccounts() {
1030
850
  }
1031
851
  export async function getBackupMetadata() {
1032
852
  const storagePath = getStoragePath();
1033
- const walPath = getAccountsWalPath(storagePath);
1034
- const accountCandidates = await getAccountsBackupRecoveryCandidatesWithDiscovery(storagePath);
1035
- const accountSnapshots = [
1036
- await describeAccountSnapshot(storagePath, "accounts-primary"),
1037
- await describeAccountsWalSnapshot(walPath),
1038
- ];
1039
- for (const [index, candidate] of accountCandidates.entries()) {
1040
- const kind = candidate === `${storagePath}.bak`
1041
- ? "accounts-backup"
1042
- : candidate.startsWith(`${storagePath}.bak.`)
1043
- ? "accounts-backup-history"
1044
- : "accounts-discovered-backup";
1045
- accountSnapshots.push(await describeAccountSnapshot(candidate, kind, index));
1046
- }
1047
853
  const flaggedPath = getFlaggedAccountsPath();
1048
- const flaggedCandidates = await getAccountsBackupRecoveryCandidatesWithDiscovery(flaggedPath);
1049
- const flaggedSnapshots = [
1050
- await describeFlaggedSnapshot(flaggedPath, "flagged-primary"),
1051
- ];
1052
- for (const [index, candidate] of flaggedCandidates.entries()) {
1053
- const kind = candidate === `${flaggedPath}.bak`
1054
- ? "flagged-backup"
1055
- : candidate.startsWith(`${flaggedPath}.bak.`)
1056
- ? "flagged-backup-history"
1057
- : "flagged-discovered-backup";
1058
- flaggedSnapshots.push(await describeFlaggedSnapshot(candidate, kind, index));
1059
- }
1060
- return {
1061
- accounts: buildMetadataSection(storagePath, accountSnapshots),
1062
- flaggedAccounts: buildMetadataSection(flaggedPath, flaggedSnapshots),
1063
- };
854
+ return buildBackupMetadata({
855
+ storagePath,
856
+ flaggedPath,
857
+ walPath: getAccountsWalPath(storagePath),
858
+ getAccountsBackupRecoveryCandidatesWithDiscovery,
859
+ describeAccountSnapshot,
860
+ describeAccountsWalSnapshot,
861
+ describeFlaggedSnapshot,
862
+ buildMetadataSection,
863
+ });
1064
864
  }
1065
865
  export async function getRestoreAssessment() {
1066
866
  const storagePath = getStoragePath();
1067
867
  const resetMarkerPath = getIntentionalResetMarkerPath(storagePath);
1068
868
  const backupMetadata = await getBackupMetadata();
1069
- if (existsSync(resetMarkerPath)) {
1070
- return {
1071
- storagePath,
1072
- restoreEligible: false,
1073
- restoreReason: "intentional-reset",
1074
- backupMetadata,
1075
- };
1076
- }
1077
- const primarySnapshot = backupMetadata.accounts.snapshots.find((snapshot) => snapshot.kind === "accounts-primary");
1078
- if (!primarySnapshot?.exists) {
1079
- return {
1080
- storagePath,
1081
- restoreEligible: true,
1082
- restoreReason: "missing-storage",
1083
- latestSnapshot: backupMetadata.accounts.latestValidPath
1084
- ? backupMetadata.accounts.snapshots.find((snapshot) => snapshot.path === backupMetadata.accounts.latestValidPath)
1085
- : undefined,
1086
- backupMetadata,
1087
- };
1088
- }
1089
- if (primarySnapshot.valid && primarySnapshot.accountCount === 0) {
1090
- return {
1091
- storagePath,
1092
- restoreEligible: true,
1093
- restoreReason: "empty-storage",
1094
- latestSnapshot: primarySnapshot,
1095
- backupMetadata,
1096
- };
1097
- }
1098
- return {
869
+ return buildRestoreAssessment({
1099
870
  storagePath,
1100
- restoreEligible: false,
1101
- latestSnapshot: backupMetadata.accounts.latestValidPath
1102
- ? backupMetadata.accounts.snapshots.find((snapshot) => snapshot.path === backupMetadata.accounts.latestValidPath)
1103
- : undefined,
1104
871
  backupMetadata,
1105
- };
1106
- }
1107
- function parseAndNormalizeStorage(data) {
1108
- const schemaErrors = getValidationErrors(AnyAccountStorageSchema, data);
1109
- const normalized = normalizeAccountStorage(data);
1110
- const storedVersion = isRecord(data)
1111
- ? data.version
1112
- : undefined;
1113
- return { normalized, storedVersion, schemaErrors };
1114
- }
1115
- async function loadAccountsFromPath(path) {
1116
- const content = await fs.readFile(path, "utf-8");
1117
- const data = JSON.parse(content);
1118
- return parseAndNormalizeStorage(data);
872
+ hasResetMarker: existsSync(resetMarkerPath),
873
+ });
1119
874
  }
1120
875
  async function loadAccountsFromJournal(path) {
1121
876
  const walPath = getAccountsWalPath(path);
@@ -1142,7 +897,7 @@ async function loadAccountsFromJournal(path) {
1142
897
  return null;
1143
898
  }
1144
899
  const data = JSON.parse(entry.content);
1145
- const { normalized } = parseAndNormalizeStorage(data);
900
+ const { normalized } = parseAndNormalizeStorage(data, normalizeAccountStorage, isRecord);
1146
901
  if (!normalized)
1147
902
  return null;
1148
903
  log.warn("Recovered account storage from WAL journal", { path, walPath });
@@ -1164,10 +919,13 @@ async function loadAccountsInternal(persistMigration) {
1164
919
  const resetMarkerPath = getIntentionalResetMarkerPath(path);
1165
920
  await cleanupStaleRotatingBackupArtifacts(path);
1166
921
  const migratedLegacyStorage = persistMigration
1167
- ? await migrateLegacyProjectStorageIfNeeded(persistMigration)
922
+ ? await migrateLegacyProjectStorageIfNeeded({ persist: persistMigration })
1168
923
  : null;
1169
924
  try {
1170
- const { normalized, storedVersion, schemaErrors } = await loadAccountsFromPath(path);
925
+ const { normalized, storedVersion, schemaErrors } = await loadAccountsFromPath(path, {
926
+ normalizeAccountStorage,
927
+ isRecord,
928
+ });
1171
929
  if (schemaErrors.length > 0) {
1172
930
  log.warn("Account storage schema validation warnings", {
1173
931
  errors: schemaErrors.slice(0, 5),
@@ -1202,7 +960,10 @@ async function loadAccountsInternal(persistMigration) {
1202
960
  if (backupPath === path)
1203
961
  continue;
1204
962
  try {
1205
- const backup = await loadAccountsFromPath(backupPath);
963
+ const backup = await loadAccountsFromPath(backupPath, {
964
+ normalizeAccountStorage,
965
+ isRecord,
966
+ });
1206
967
  if (!backup.normalized)
1207
968
  continue;
1208
969
  if (looksLikeSyntheticFixtureStorage(backup.normalized))
@@ -1271,7 +1032,10 @@ async function loadAccountsInternal(persistMigration) {
1271
1032
  const backupCandidates = await getAccountsBackupRecoveryCandidatesWithDiscovery(path);
1272
1033
  for (const backupPath of backupCandidates) {
1273
1034
  try {
1274
- const backup = await loadAccountsFromPath(backupPath);
1035
+ const backup = await loadAccountsFromPath(backupPath, {
1036
+ normalizeAccountStorage,
1037
+ isRecord,
1038
+ });
1275
1039
  if (backup.schemaErrors.length > 0) {
1276
1040
  log.warn("Backup account storage schema validation warnings", {
1277
1041
  path: backupPath,
@@ -1317,151 +1081,179 @@ async function loadAccountsInternal(persistMigration) {
1317
1081
  return null;
1318
1082
  }
1319
1083
  }
1084
+ async function loadAccountsForExport() {
1085
+ // Export reuses this helper from both paths in `exportAccounts()`. Keep the
1086
+ // read side effect free so export never clears a reset marker or races with
1087
+ // concurrent writers while normalizing legacy storage for the snapshot.
1088
+ const path = getStoragePath();
1089
+ const resetMarkerPath = getIntentionalResetMarkerPath(path);
1090
+ if (existsSync(resetMarkerPath)) {
1091
+ return createEmptyStorageWithMetadata(false, "intentional-reset");
1092
+ }
1093
+ try {
1094
+ const { normalized, schemaErrors } = await loadAccountsFromPath(path, {
1095
+ normalizeAccountStorage,
1096
+ isRecord,
1097
+ });
1098
+ if (schemaErrors.length > 0) {
1099
+ log.warn("Account storage schema validation warnings", {
1100
+ errors: schemaErrors.slice(0, 5),
1101
+ });
1102
+ }
1103
+ if (existsSync(resetMarkerPath)) {
1104
+ return createEmptyStorageWithMetadata(false, "intentional-reset");
1105
+ }
1106
+ return normalized;
1107
+ }
1108
+ catch (error) {
1109
+ const code = error.code;
1110
+ if (existsSync(resetMarkerPath)) {
1111
+ return createEmptyStorageWithMetadata(false, "intentional-reset");
1112
+ }
1113
+ if (code === "ENOENT") {
1114
+ const migratedLegacyStorage = await migrateLegacyProjectStorageIfNeeded({ commit: false });
1115
+ if (existsSync(resetMarkerPath)) {
1116
+ return createEmptyStorageWithMetadata(false, "intentional-reset");
1117
+ }
1118
+ return migratedLegacyStorage;
1119
+ }
1120
+ throw error;
1121
+ }
1122
+ }
1320
1123
  async function saveAccountsUnlocked(storage) {
1321
1124
  const path = getStoragePath();
1322
1125
  const resetMarkerPath = getIntentionalResetMarkerPath(path);
1323
- const uniqueSuffix = `${Date.now()}.${Math.random().toString(36).slice(2, 8)}`;
1324
- const tempPath = `${path}.${uniqueSuffix}.tmp`;
1325
1126
  const walPath = getAccountsWalPath(path);
1326
- try {
1327
- await fs.mkdir(dirname(path), { recursive: true });
1328
- await ensureGitignore(path);
1329
- if (looksLikeSyntheticFixtureStorage(storage)) {
1330
- try {
1331
- const existing = await loadNormalizedStorageFromPath(path, "existing account storage");
1332
- if (existing &&
1333
- existing.accounts.length > 0 &&
1334
- !looksLikeSyntheticFixtureStorage(existing)) {
1335
- throw new StorageError("Refusing to overwrite non-synthetic account storage with synthetic fixture payload", "EINVALID", path, "Detected synthetic fixture-like account payload. Use explicit account import/login commands instead.");
1127
+ return saveAccountsToDisk(storage, {
1128
+ path,
1129
+ resetMarkerPath,
1130
+ walPath,
1131
+ storageBackupEnabled: storageBackupEnabled && existsSync(path),
1132
+ ensureDirectory: async () => {
1133
+ await fs.mkdir(dirname(path), { recursive: true });
1134
+ },
1135
+ ensureGitignore: () => ensureGitignore(path),
1136
+ looksLikeSyntheticFixtureStorage,
1137
+ loadExistingStorage: () => loadNormalizedStorageFromPath(path, "existing account storage", {
1138
+ loadAccountsFromPath: (candidatePath) => loadAccountsFromPath(candidatePath, {
1139
+ normalizeAccountStorage,
1140
+ isRecord,
1141
+ }),
1142
+ logWarn: (message, details) => {
1143
+ log.warn(message, details);
1144
+ },
1145
+ }),
1146
+ createSyntheticFixtureError: () => new StorageError("Refusing to overwrite non-synthetic account storage with synthetic fixture payload", "EINVALID", path, "Detected synthetic fixture-like account payload. Use explicit account import/login commands instead."),
1147
+ createRotatingAccountsBackup,
1148
+ computeSha256,
1149
+ writeJournal: async (content, journalPath) => {
1150
+ const journalEntry = {
1151
+ version: 1,
1152
+ createdAt: Date.now(),
1153
+ path: journalPath,
1154
+ checksum: computeSha256(content),
1155
+ content,
1156
+ };
1157
+ await fs.writeFile(walPath, JSON.stringify(journalEntry), {
1158
+ encoding: "utf-8",
1159
+ mode: 0o600,
1160
+ });
1161
+ },
1162
+ writeTemp: (tempPath, content) => fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 }),
1163
+ statTemp: (tempPath) => fs.stat(tempPath),
1164
+ renameTempToPath: async (tempPath) => {
1165
+ let lastError = null;
1166
+ for (let attempt = 0; attempt < 5; attempt++) {
1167
+ try {
1168
+ await fs.rename(tempPath, path);
1169
+ return;
1336
1170
  }
1337
- }
1338
- catch (error) {
1339
- if (error instanceof StorageError) {
1340
- throw error;
1171
+ catch (renameError) {
1172
+ const code = renameError.code;
1173
+ if (code === "EPERM" || code === "EBUSY") {
1174
+ lastError = renameError;
1175
+ await new Promise((r) => setTimeout(r, 10 * 2 ** attempt));
1176
+ continue;
1177
+ }
1178
+ throw renameError;
1341
1179
  }
1342
- // Ignore existing-file probe failures and continue with normal save flow.
1343
1180
  }
1344
- }
1345
- if (storageBackupEnabled && existsSync(path)) {
1181
+ if (lastError)
1182
+ throw lastError;
1183
+ },
1184
+ cleanupResetMarker: async () => {
1346
1185
  try {
1347
- await createRotatingAccountsBackup(path);
1186
+ await fs.unlink(resetMarkerPath);
1348
1187
  }
1349
- catch (backupError) {
1350
- log.warn("Failed to create account storage backup", {
1351
- path,
1352
- backupPath: getAccountsBackupPath(path),
1353
- error: String(backupError),
1354
- });
1188
+ catch {
1189
+ // Best effort cleanup.
1355
1190
  }
1356
- }
1357
- const content = JSON.stringify(storage, null, 2);
1358
- const journalEntry = {
1359
- version: 1,
1360
- createdAt: Date.now(),
1361
- path,
1362
- checksum: computeSha256(content),
1363
- content,
1364
- };
1365
- await fs.writeFile(walPath, JSON.stringify(journalEntry), {
1366
- encoding: "utf-8",
1367
- mode: 0o600,
1368
- });
1369
- await fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 });
1370
- const stats = await fs.stat(tempPath);
1371
- if (stats.size === 0) {
1372
- const emptyError = Object.assign(new Error("File written but size is 0"), { code: "EEMPTY" });
1373
- throw emptyError;
1374
- }
1375
- // Retry rename with exponential backoff for Windows EPERM/EBUSY
1376
- let lastError = null;
1377
- for (let attempt = 0; attempt < 5; attempt++) {
1191
+ },
1192
+ cleanupWal: async () => {
1378
1193
  try {
1379
- await fs.rename(tempPath, path);
1380
- try {
1381
- await fs.unlink(resetMarkerPath);
1382
- }
1383
- catch {
1384
- // Best effort cleanup.
1385
- }
1386
- lastAccountsSaveTimestamp = Date.now();
1387
- try {
1388
- await fs.unlink(walPath);
1389
- }
1390
- catch {
1391
- // Best effort cleanup.
1392
- }
1393
- return;
1194
+ await fs.unlink(walPath);
1394
1195
  }
1395
- catch (renameError) {
1396
- const code = renameError.code;
1397
- if (code === "EPERM" || code === "EBUSY") {
1398
- lastError = renameError;
1399
- await new Promise((r) => setTimeout(r, 10 * 2 ** attempt));
1400
- continue;
1401
- }
1402
- throw renameError;
1196
+ catch {
1197
+ // Best effort cleanup.
1403
1198
  }
1404
- }
1405
- if (lastError)
1406
- throw lastError;
1407
- }
1408
- catch (error) {
1409
- try {
1410
- await fs.unlink(tempPath);
1411
- }
1412
- catch {
1413
- // Ignore cleanup failure.
1414
- }
1415
- const err = error;
1416
- const code = err?.code || "UNKNOWN";
1417
- const hint = formatStorageErrorHint(error, path);
1418
- log.error("Failed to save accounts", {
1419
- path,
1420
- code,
1421
- message: err?.message,
1422
- hint,
1423
- });
1424
- throw new StorageError(`Failed to save accounts: ${err?.message || "Unknown error"}`, code, path, hint, err instanceof Error ? err : undefined);
1425
- }
1199
+ },
1200
+ cleanupTemp: async (tempPath) => {
1201
+ try {
1202
+ await fs.unlink(tempPath);
1203
+ }
1204
+ catch {
1205
+ // Ignore cleanup failure.
1206
+ }
1207
+ },
1208
+ onSaved: () => {
1209
+ lastAccountsSaveTimestamp = Date.now();
1210
+ },
1211
+ logWarn: (message, details) => {
1212
+ log.warn(message, details);
1213
+ },
1214
+ logError: (message, details) => {
1215
+ log.error(message, details);
1216
+ },
1217
+ createStorageError: (error) => {
1218
+ const err = error;
1219
+ const code = err?.code || "UNKNOWN";
1220
+ const hint = formatStorageErrorHint(error, path);
1221
+ return new StorageError(`Failed to save accounts: ${err?.message || "Unknown error"}`, code, path, hint, err instanceof Error ? err : undefined);
1222
+ },
1223
+ backupPath: getAccountsBackupPath(path),
1224
+ createTempPath: () => `${path}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`,
1225
+ });
1426
1226
  }
1427
- function cloneAccountStorageForPersistence(storage) {
1227
+ function cloneFlaggedStorageForPersistence(storage) {
1428
1228
  return {
1429
- version: 3,
1229
+ version: 1,
1430
1230
  accounts: structuredClone(storage?.accounts ?? []),
1431
- activeIndex: typeof storage?.activeIndex === "number" &&
1432
- Number.isFinite(storage.activeIndex)
1433
- ? storage.activeIndex
1434
- : 0,
1435
- activeIndexByFamily: structuredClone(storage?.activeIndexByFamily ?? {}),
1436
1231
  };
1437
1232
  }
1438
1233
  export async function withAccountStorageTransaction(handler) {
1439
- return withStorageLock(async () => {
1440
- const state = {
1441
- snapshot: await loadAccountsInternal(saveAccountsUnlocked),
1442
- active: true,
1443
- };
1444
- const current = state.snapshot;
1445
- const persist = async (storage) => {
1446
- await saveAccountsUnlocked(storage);
1447
- state.snapshot = storage;
1448
- };
1449
- return transactionSnapshotContext.run(state, () => handler(current, persist));
1234
+ return runWithAccountStorageTransaction(handler, {
1235
+ getStoragePath,
1236
+ loadCurrent: () => loadAccountsInternal(saveAccountsUnlocked),
1237
+ saveAccounts: saveAccountsUnlocked,
1450
1238
  });
1451
1239
  }
1452
1240
  export async function withAccountAndFlaggedStorageTransaction(handler) {
1453
1241
  return withStorageLock(async () => {
1242
+ const storagePath = getStoragePath();
1454
1243
  const state = {
1455
1244
  snapshot: await loadAccountsInternal(saveAccountsUnlocked),
1245
+ storagePath,
1456
1246
  active: true,
1457
1247
  };
1458
1248
  const current = state.snapshot;
1249
+ const currentFlagged = await loadFlaggedAccounts();
1459
1250
  const persist = async (accountStorage, flaggedStorage) => {
1460
1251
  const previousAccounts = cloneAccountStorageForPersistence(state.snapshot);
1461
1252
  const nextAccounts = cloneAccountStorageForPersistence(accountStorage);
1253
+ const nextFlagged = cloneFlaggedStorageForPersistence(flaggedStorage);
1462
1254
  await saveAccountsUnlocked(nextAccounts);
1463
1255
  try {
1464
- await saveFlaggedAccountsUnlocked(flaggedStorage);
1256
+ await saveFlaggedAccountsUnlocked(nextFlagged);
1465
1257
  state.snapshot = nextAccounts;
1466
1258
  }
1467
1259
  catch (error) {
@@ -1480,7 +1272,37 @@ export async function withAccountAndFlaggedStorageTransaction(handler) {
1480
1272
  throw error;
1481
1273
  }
1482
1274
  };
1483
- return transactionSnapshotContext.run(state, () => handler(current, persist));
1275
+ return runInTransactionSnapshotContext(state, () => handler(current, persist, currentFlagged));
1276
+ });
1277
+ }
1278
+ export async function withFlaggedStorageTransaction(handler) {
1279
+ return withStorageLock(async () => {
1280
+ const current = await loadFlaggedAccounts();
1281
+ let snapshot = cloneFlaggedStorageForPersistence(current);
1282
+ const persist = async (storage) => {
1283
+ const previousStorage = cloneFlaggedStorageForPersistence(snapshot);
1284
+ const nextStorage = cloneFlaggedStorageForPersistence(storage);
1285
+ try {
1286
+ await saveFlaggedAccountsUnlocked(nextStorage);
1287
+ snapshot = nextStorage;
1288
+ }
1289
+ catch (error) {
1290
+ try {
1291
+ await saveFlaggedAccountsUnlocked(previousStorage);
1292
+ snapshot = previousStorage;
1293
+ }
1294
+ catch (rollbackError) {
1295
+ const combinedError = new AggregateError([error, rollbackError], "Flagged save failed and flagged storage rollback also failed");
1296
+ log.error("Failed to rollback flagged storage after flagged save failure", {
1297
+ error: String(error),
1298
+ rollbackError: String(rollbackError),
1299
+ });
1300
+ throw combinedError;
1301
+ }
1302
+ throw error;
1303
+ }
1304
+ };
1305
+ return handler(structuredClone(snapshot), persist);
1484
1306
  });
1485
1307
  }
1486
1308
  /**
@@ -1491,8 +1313,10 @@ export async function withAccountAndFlaggedStorageTransaction(handler) {
1491
1313
  * @throws StorageError with platform-aware hints on failure
1492
1314
  */
1493
1315
  export async function saveAccounts(storage) {
1494
- return withStorageLock(async () => {
1495
- await saveAccountsUnlocked(storage);
1316
+ return saveAccountsEntry({
1317
+ storage,
1318
+ withStorageLock,
1319
+ saveUnlocked: saveAccountsUnlocked,
1496
1320
  });
1497
1321
  }
1498
1322
  /**
@@ -1500,265 +1324,75 @@ export async function saveAccounts(storage) {
1500
1324
  * Silently ignores if file doesn't exist.
1501
1325
  */
1502
1326
  export async function clearAccounts() {
1503
- return withStorageLock(async () => {
1504
- const path = getStoragePath();
1505
- const resetMarkerPath = getIntentionalResetMarkerPath(path);
1506
- const walPath = getAccountsWalPath(path);
1507
- const backupPaths = await getAccountsBackupRecoveryCandidatesWithDiscovery(path);
1508
- await fs.writeFile(resetMarkerPath, JSON.stringify({ version: 1, createdAt: Date.now() }), { encoding: "utf-8", mode: 0o600 });
1509
- const clearPath = async (targetPath) => {
1510
- try {
1511
- await fs.unlink(targetPath);
1512
- }
1513
- catch (error) {
1514
- const code = error.code;
1515
- if (code !== "ENOENT") {
1516
- log.error("Failed to clear account storage artifact", {
1517
- path: targetPath,
1518
- error: String(error),
1519
- });
1520
- }
1521
- }
1522
- };
1523
- try {
1524
- await Promise.all([
1525
- clearPath(path),
1526
- clearPath(walPath),
1527
- ...backupPaths.map(clearPath),
1528
- ]);
1529
- }
1530
- catch {
1531
- // Individual path cleanup is already best-effort with per-artifact logging.
1532
- }
1327
+ const path = getStoragePath();
1328
+ return clearAccountsEntry({
1329
+ path,
1330
+ withStorageLock,
1331
+ resetMarkerPath: getIntentionalResetMarkerPath(path),
1332
+ walPath: getAccountsWalPath(path),
1333
+ getBackupPaths: () => getAccountsBackupRecoveryCandidatesWithDiscovery(path),
1334
+ clearAccountStorageArtifacts,
1335
+ logError: (message, details) => {
1336
+ log.error(message, details);
1337
+ },
1533
1338
  });
1534
1339
  }
1535
- function normalizeFlaggedStorage(data) {
1536
- if (!isRecord(data) || data.version !== 1 || !Array.isArray(data.accounts)) {
1537
- return { version: 1, accounts: [] };
1538
- }
1539
- const byRefreshToken = new Map();
1540
- for (const rawAccount of data.accounts) {
1541
- if (!isRecord(rawAccount))
1542
- continue;
1543
- const refreshToken = typeof rawAccount.refreshToken === "string"
1544
- ? rawAccount.refreshToken.trim()
1545
- : "";
1546
- if (!refreshToken)
1547
- continue;
1548
- const flaggedAt = typeof rawAccount.flaggedAt === "number"
1549
- ? rawAccount.flaggedAt
1550
- : Date.now();
1551
- const isAccountIdSource = (value) => value === "token" ||
1552
- value === "id_token" ||
1553
- value === "org" ||
1554
- value === "manual";
1555
- const isSwitchReason = (value) => value === "rate-limit" ||
1556
- value === "initial" ||
1557
- value === "rotation" ||
1558
- value === "best";
1559
- const isCooldownReason = (value) => value === "auth-failure" ||
1560
- value === "network-error" ||
1561
- value === "rate-limit";
1562
- let rateLimitResetTimes;
1563
- if (isRecord(rawAccount.rateLimitResetTimes)) {
1564
- const normalizedRateLimits = {};
1565
- for (const [key, value] of Object.entries(rawAccount.rateLimitResetTimes)) {
1566
- if (typeof value === "number") {
1567
- normalizedRateLimits[key] = value;
1568
- }
1569
- }
1570
- if (Object.keys(normalizedRateLimits).length > 0) {
1571
- rateLimitResetTimes = normalizedRateLimits;
1572
- }
1573
- }
1574
- const accountIdSource = isAccountIdSource(rawAccount.accountIdSource)
1575
- ? rawAccount.accountIdSource
1576
- : undefined;
1577
- const lastSwitchReason = isSwitchReason(rawAccount.lastSwitchReason)
1578
- ? rawAccount.lastSwitchReason
1579
- : undefined;
1580
- const cooldownReason = isCooldownReason(rawAccount.cooldownReason)
1581
- ? rawAccount.cooldownReason
1582
- : undefined;
1583
- const normalized = {
1584
- refreshToken,
1585
- addedAt: typeof rawAccount.addedAt === "number" ? rawAccount.addedAt : flaggedAt,
1586
- lastUsed: typeof rawAccount.lastUsed === "number"
1587
- ? rawAccount.lastUsed
1588
- : flaggedAt,
1589
- accountId: typeof rawAccount.accountId === "string"
1590
- ? rawAccount.accountId
1591
- : undefined,
1592
- accountIdSource,
1593
- accountLabel: typeof rawAccount.accountLabel === "string"
1594
- ? rawAccount.accountLabel
1595
- : undefined,
1596
- email: typeof rawAccount.email === "string" ? rawAccount.email : undefined,
1597
- enabled: typeof rawAccount.enabled === "boolean"
1598
- ? rawAccount.enabled
1599
- : undefined,
1600
- lastSwitchReason,
1601
- rateLimitResetTimes,
1602
- coolingDownUntil: typeof rawAccount.coolingDownUntil === "number"
1603
- ? rawAccount.coolingDownUntil
1604
- : undefined,
1605
- cooldownReason,
1606
- flaggedAt,
1607
- flaggedReason: typeof rawAccount.flaggedReason === "string"
1608
- ? rawAccount.flaggedReason
1609
- : undefined,
1610
- lastError: typeof rawAccount.lastError === "string"
1611
- ? rawAccount.lastError
1612
- : undefined,
1613
- };
1614
- byRefreshToken.set(refreshToken, normalized);
1615
- }
1616
- return {
1617
- version: 1,
1618
- accounts: Array.from(byRefreshToken.values()),
1619
- };
1620
- }
1621
1340
  export async function loadFlaggedAccounts() {
1622
- const path = getFlaggedAccountsPath();
1623
- const resetMarkerPath = getIntentionalResetMarkerPath(path);
1624
- const empty = { version: 1, accounts: [] };
1625
- try {
1626
- const content = await fs.readFile(path, "utf-8");
1627
- const data = JSON.parse(content);
1628
- const loaded = normalizeFlaggedStorage(data);
1629
- if (existsSync(resetMarkerPath)) {
1630
- return empty;
1631
- }
1632
- return loaded;
1633
- }
1634
- catch (error) {
1635
- const code = error.code;
1636
- if (code !== "ENOENT") {
1637
- log.error("Failed to load flagged account storage", {
1638
- path,
1639
- error: String(error),
1640
- });
1641
- return empty;
1642
- }
1643
- }
1644
- const legacyPath = getLegacyFlaggedAccountsPath();
1645
- if (!existsSync(legacyPath)) {
1646
- return empty;
1647
- }
1648
- try {
1649
- const legacyContent = await fs.readFile(legacyPath, "utf-8");
1650
- const legacyData = JSON.parse(legacyContent);
1651
- const migrated = normalizeFlaggedStorage(legacyData);
1652
- if (migrated.accounts.length > 0) {
1653
- await saveFlaggedAccounts(migrated);
1654
- }
1655
- try {
1656
- await fs.unlink(legacyPath);
1657
- }
1658
- catch {
1659
- // Best effort cleanup.
1660
- }
1661
- log.info("Migrated legacy flagged account storage", {
1662
- from: legacyPath,
1663
- to: path,
1664
- accounts: migrated.accounts.length,
1665
- });
1666
- return migrated;
1667
- }
1668
- catch (error) {
1669
- log.error("Failed to migrate legacy flagged account storage", {
1670
- from: legacyPath,
1671
- to: path,
1672
- error: String(error),
1673
- });
1674
- return empty;
1675
- }
1341
+ return loadFlaggedAccountsEntry({
1342
+ getFlaggedAccountsPath,
1343
+ getLegacyFlaggedAccountsPath,
1344
+ getIntentionalResetMarkerPath,
1345
+ normalizeFlaggedStorage: (data) => normalizeFlaggedStorage(data, {
1346
+ isRecord,
1347
+ now: () => Date.now(),
1348
+ }),
1349
+ saveFlaggedAccounts,
1350
+ loadFlaggedAccountsState,
1351
+ logError: (message, details) => {
1352
+ log.error(message, details);
1353
+ },
1354
+ logInfo: (message, details) => {
1355
+ log.info(message, details);
1356
+ },
1357
+ });
1676
1358
  }
1677
1359
  async function saveFlaggedAccountsUnlocked(storage) {
1678
1360
  const path = getFlaggedAccountsPath();
1679
- const markerPath = getIntentionalResetMarkerPath(path);
1680
- const uniqueSuffix = `${Date.now()}.${Math.random().toString(36).slice(2, 8)}`;
1681
- const tempPath = `${path}.${uniqueSuffix}.tmp`;
1682
- try {
1683
- await fs.mkdir(dirname(path), { recursive: true });
1684
- if (existsSync(path)) {
1685
- try {
1686
- await copyFileWithRetry(path, `${path}.bak`, {
1687
- allowMissingSource: true,
1688
- });
1689
- }
1690
- catch (backupError) {
1691
- log.warn("Failed to create flagged backup snapshot", {
1692
- path,
1693
- error: String(backupError),
1694
- });
1695
- }
1696
- }
1697
- const content = JSON.stringify(normalizeFlaggedStorage(storage), null, 2);
1698
- await fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 });
1699
- await renameFileWithRetry(tempPath, path);
1700
- try {
1701
- await fs.unlink(markerPath);
1702
- }
1703
- catch {
1704
- // Best effort cleanup.
1705
- }
1706
- }
1707
- catch (error) {
1708
- try {
1709
- await fs.unlink(tempPath);
1710
- }
1711
- catch {
1712
- // Ignore cleanup failures.
1713
- }
1714
- log.error("Failed to save flagged account storage", {
1715
- path,
1716
- error: String(error),
1717
- });
1718
- throw error;
1719
- }
1361
+ return saveFlaggedAccountsUnlockedToDisk(storage, {
1362
+ path,
1363
+ markerPath: getIntentionalResetMarkerPath(path),
1364
+ normalizeFlaggedStorage: (data) => normalizeFlaggedStorage(data, {
1365
+ isRecord,
1366
+ now: () => Date.now(),
1367
+ }),
1368
+ copyFileWithRetry,
1369
+ renameFileWithRetry,
1370
+ logWarn: (message, details) => {
1371
+ log.warn(message, details);
1372
+ },
1373
+ logError: (message, details) => {
1374
+ log.error(message, details);
1375
+ },
1376
+ });
1720
1377
  }
1721
1378
  export async function saveFlaggedAccounts(storage) {
1722
- return withStorageLock(async () => {
1723
- await saveFlaggedAccountsUnlocked(storage);
1379
+ return saveFlaggedAccountsEntry({
1380
+ storage,
1381
+ withStorageLock,
1382
+ saveUnlocked: saveFlaggedAccountsUnlocked,
1724
1383
  });
1725
1384
  }
1726
1385
  export async function clearFlaggedAccounts() {
1727
- return withStorageLock(async () => {
1728
- const path = getFlaggedAccountsPath();
1729
- const markerPath = getIntentionalResetMarkerPath(path);
1730
- try {
1731
- await fs.writeFile(markerPath, "reset", {
1732
- encoding: "utf-8",
1733
- mode: 0o600,
1734
- });
1735
- }
1736
- catch (error) {
1737
- log.error("Failed to write flagged reset marker", {
1738
- path,
1739
- markerPath,
1740
- error: String(error),
1741
- });
1742
- throw error;
1743
- }
1744
- const backupPaths = await getAccountsBackupRecoveryCandidatesWithDiscovery(path);
1745
- for (const candidate of [path, ...backupPaths, markerPath]) {
1746
- try {
1747
- await fs.unlink(candidate);
1748
- }
1749
- catch (error) {
1750
- const code = error.code;
1751
- if (code !== "ENOENT") {
1752
- log.error("Failed to clear flagged account storage", {
1753
- path: candidate,
1754
- error: String(error),
1755
- });
1756
- if (candidate === path) {
1757
- throw error;
1758
- }
1759
- }
1760
- }
1761
- }
1386
+ const path = getFlaggedAccountsPath();
1387
+ return clearFlaggedAccountsEntry({
1388
+ path,
1389
+ withStorageLock,
1390
+ markerPath: getIntentionalResetMarkerPath(path),
1391
+ getBackupPaths: () => getAccountsBackupRecoveryCandidatesWithDiscovery(path),
1392
+ clearFlaggedAccountsOnDisk,
1393
+ logError: (message, details) => {
1394
+ log.error(message, details);
1395
+ },
1762
1396
  });
1763
1397
  }
1764
1398
  /**
@@ -1769,31 +1403,19 @@ export async function clearFlaggedAccounts() {
1769
1403
  */
1770
1404
  export async function exportAccounts(filePath, force = true, beforeCommit) {
1771
1405
  const resolvedPath = resolvePath(filePath);
1772
- if (!force && existsSync(resolvedPath)) {
1773
- throw new Error(`File already exists: ${resolvedPath}`);
1774
- }
1775
- const transactionState = transactionSnapshotContext.getStore();
1776
- const storage = transactionState?.active
1777
- ? transactionState.snapshot
1778
- : await withAccountStorageTransaction((current) => Promise.resolve(current));
1779
- if (!storage || storage.accounts.length === 0) {
1780
- throw new Error("No accounts to export");
1781
- }
1782
- await fs.mkdir(dirname(resolvedPath), { recursive: true });
1783
- await beforeCommit?.(resolvedPath);
1784
- if (!force && existsSync(resolvedPath)) {
1785
- throw new Error(`File already exists: ${resolvedPath}`);
1786
- }
1787
- const content = JSON.stringify({
1788
- version: storage.version,
1789
- accounts: storage.accounts,
1790
- activeIndex: storage.activeIndex,
1791
- activeIndexByFamily: storage.activeIndexByFamily,
1792
- }, null, 2);
1793
- await fs.writeFile(resolvedPath, content, { encoding: "utf-8", mode: 0o600 });
1794
- log.info("Exported accounts", {
1795
- path: resolvedPath,
1796
- count: storage.accounts.length,
1406
+ const currentStoragePath = getStoragePath();
1407
+ await exportAccountsSnapshot({
1408
+ resolvedPath,
1409
+ force,
1410
+ currentStoragePath,
1411
+ transactionState: getTransactionSnapshotState(),
1412
+ readCurrentStorageUnlocked: () => loadAccountsForExport(),
1413
+ readCurrentStorage: () => withStorageLock(() => loadAccountsForExport()),
1414
+ exportAccountsToFile,
1415
+ beforeCommit,
1416
+ logInfo: (message, details) => {
1417
+ log.info(message, details);
1418
+ },
1797
1419
  });
1798
1420
  }
1799
1421
  /**
@@ -1804,50 +1426,17 @@ export async function exportAccounts(filePath, force = true, beforeCommit) {
1804
1426
  */
1805
1427
  export async function importAccounts(filePath) {
1806
1428
  const resolvedPath = resolvePath(filePath);
1807
- // Check file exists with friendly error
1808
- if (!existsSync(resolvedPath)) {
1809
- throw new Error(`Import file not found: ${resolvedPath}`);
1810
- }
1811
- const content = await fs.readFile(resolvedPath, "utf-8");
1812
- let imported;
1813
- try {
1814
- imported = JSON.parse(content);
1815
- }
1816
- catch {
1817
- throw new Error(`Invalid JSON in import file: ${resolvedPath}`);
1818
- }
1819
- const normalized = normalizeAccountStorage(imported);
1820
- if (!normalized) {
1821
- throw new Error("Invalid account storage format");
1822
- }
1823
- const { imported: importedCount, total, skipped: skippedCount, } = await withAccountStorageTransaction(async (existing, persist) => {
1824
- const existingAccounts = existing?.accounts ?? [];
1825
- const existingActiveIndex = existing?.activeIndex ?? 0;
1826
- const merged = [...existingAccounts, ...normalized.accounts];
1827
- if (merged.length > ACCOUNT_LIMITS.MAX_ACCOUNTS) {
1828
- const deduped = deduplicateAccounts(merged);
1829
- if (deduped.length > ACCOUNT_LIMITS.MAX_ACCOUNTS) {
1830
- throw new Error(`Import would exceed maximum of ${ACCOUNT_LIMITS.MAX_ACCOUNTS} accounts (would have ${deduped.length})`);
1831
- }
1832
- }
1833
- const deduplicatedAccounts = deduplicateAccounts(merged);
1834
- const newStorage = {
1835
- version: 3,
1836
- accounts: deduplicatedAccounts,
1837
- activeIndex: existingActiveIndex,
1838
- activeIndexByFamily: existing?.activeIndexByFamily,
1839
- };
1840
- await persist(newStorage);
1841
- const imported = deduplicatedAccounts.length - existingAccounts.length;
1842
- const skipped = normalized.accounts.length - imported;
1843
- return { imported, total: deduplicatedAccounts.length, skipped };
1844
- });
1845
- log.info("Imported accounts", {
1846
- path: resolvedPath,
1847
- imported: importedCount,
1848
- skipped: skippedCount,
1849
- total,
1429
+ return importAccountsSnapshot({
1430
+ resolvedPath,
1431
+ readImportFile,
1432
+ normalizeAccountStorage,
1433
+ withAccountStorageTransaction,
1434
+ mergeImportedAccounts,
1435
+ maxAccounts: ACCOUNT_LIMITS.MAX_ACCOUNTS,
1436
+ deduplicateAccounts,
1437
+ logInfo: (message, details) => {
1438
+ log.info(message, details);
1439
+ },
1850
1440
  });
1851
- return { imported: importedCount, total, skipped: skippedCount };
1852
1441
  }
1853
1442
  //# sourceMappingURL=storage.js.map