@metabase/cli 0.2.1 → 0.2.2-alpha.extract-api-client.27e2241

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 (324) hide show
  1. package/README.md +4 -1715
  2. package/dist/add-collection-B3Ty8SzB.mjs +36 -0
  3. package/dist/alert-DT-ee7yf.mjs +23 -0
  4. package/dist/alerts-Bf2RH_p_.mjs +43 -0
  5. package/dist/{append-BgDaYJW9.mjs → append-DFzQRPMd.mjs} +7 -12
  6. package/dist/{archive-DFCu5hVG.mjs → archive-4tmm946K.mjs} +8 -17
  7. package/dist/{archive-Bv59HYsU.mjs → archive-B6eXiyER.mjs} +7 -13
  8. package/dist/{archive-BM9HjJHQ.mjs → archive-BxNPHxOY.mjs} +7 -13
  9. package/dist/archive-ByvA49Kz.mjs +34 -0
  10. package/dist/{archive-Oh1iZu2y.mjs → archive-C7w49Grr.mjs} +7 -16
  11. package/dist/{archive-EoYl-lS-.mjs → archive-Cd29QC0c.mjs} +7 -13
  12. package/dist/{archive-BZpXnQSu.mjs → archive-ChORH5JH.mjs} +7 -13
  13. package/dist/archive-CwAdlv63.mjs +33 -0
  14. package/dist/{archive-BncW2dGw.mjs → archive-Dr9Xnx_Z.mjs} +7 -15
  15. package/dist/{archive-BCPA0HhV.mjs → archive-gid9Y09v.mjs} +8 -17
  16. package/dist/{archive-Czzktgho.mjs → archive-lQqs13Uz.mjs} +7 -13
  17. package/dist/auth-Dltxua89.mjs +19 -0
  18. package/dist/{body-DKcQw7G5.mjs → body-Cur4NJt9.mjs} +5 -8
  19. package/dist/{body-flags-CgHgJBRC.mjs → body-flags-AqKpN01Y.mjs} +1 -2
  20. package/dist/{branches-CCmtr3W8.mjs → branches-DchlyU0i.mjs} +7 -13
  21. package/dist/{cancel-72y10-Rg.mjs → cancel-BMQa5R1Z.mjs} +5 -12
  22. package/dist/{cancel-task-CGwdz91O.mjs → cancel-task-C5CU1pxU.mjs} +6 -10
  23. package/dist/card-CHI2bmds.mjs +24 -0
  24. package/dist/{card-B8G5jQQT.mjs → card-DZxRmver.mjs} +21 -48
  25. package/dist/card-zyUkr2nS.mjs +44 -0
  26. package/dist/cards-SccWvRQD.mjs +34 -0
  27. package/dist/cli.mjs +675 -81
  28. package/dist/client-BqhzKdLM.mjs +2194 -0
  29. package/dist/collection-CGoVLvcD.mjs +58 -0
  30. package/dist/collection-CY0AB99E.mjs +20 -0
  31. package/dist/{collection-CFoLPrY5.mjs → collection-CfulNRBG.mjs} +20 -63
  32. package/dist/{collection-namespace-C7mr_a8H.mjs → collection-namespace-GwydWBF3.mjs} +3 -5
  33. package/dist/{create-pTnveKkm.mjs → create-BNQ_DytP.mjs} +8 -15
  34. package/dist/{create-QYctYGSa.mjs → create-BOLwWt8Q.mjs} +9 -17
  35. package/dist/{create-C_WqoOf5.mjs → create-Beh-2uoN.mjs} +8 -15
  36. package/dist/{create-C3DThF9E.mjs → create-C79vErX0.mjs} +9 -20
  37. package/dist/{create-nXlnVzXl.mjs → create-CAQV2g6V.mjs} +9 -16
  38. package/dist/{create-E7XhC0gJ.mjs → create-CAWytBE5.mjs} +9 -17
  39. package/dist/{create-CPEOSxIH.mjs → create-CCh_LyW9.mjs} +8 -15
  40. package/dist/{create-7pbf5Wu0.mjs → create-CD008jdE.mjs} +13 -28
  41. package/dist/create-CHQx7jq4.mjs +45 -0
  42. package/dist/create-DF4QtgDL.mjs +44 -0
  43. package/dist/{create-CaWFrPRU.mjs → create-DJmXXQoq.mjs} +10 -18
  44. package/dist/{create-Brh8WCa3.mjs → create-DV-Ln5Mo.mjs} +8 -15
  45. package/dist/create-branch-CYo6jZth.mjs +35 -0
  46. package/dist/{create-U_XDwsIX.mjs → create-i14Wv3Tj.mjs} +8 -15
  47. package/dist/{create-BDY38_Kr.mjs → create-tQbnuz-I.mjs} +8 -15
  48. package/dist/{create-DFyZCXQD.mjs → create-zeveFdnd.mjs} +6 -10
  49. package/dist/cron-LKRffEC-.mjs +5 -0
  50. package/dist/{csv-CR2qhmC6.mjs → csv-B2Jgb1GM.mjs} +7 -19
  51. package/dist/{current-task-MUHaiHIg.mjs → current-task-MpBFGttd.mjs} +7 -12
  52. package/dist/{dashboard-B-MTpfeS.mjs → dashboard-BCpSq_G-.mjs} +9 -60
  53. package/dist/dashboard-BHJBoaG7.mjs +33 -0
  54. package/dist/dashboard-CsIFFpzK.mjs +58 -0
  55. package/dist/database-B19qlLKZ.mjs +38 -0
  56. package/dist/database-C8G6ZKG0.mjs +26 -0
  57. package/dist/db-DsfojyeH.mjs +24 -0
  58. package/dist/{delete-B58Cng0p.mjs → delete-B8e01xAG.mjs} +6 -11
  59. package/dist/{delete-CW3dYmuT.mjs → delete-BApOjQvl.mjs} +6 -11
  60. package/dist/{delete-doa3R-c5.mjs → delete-Ck0q4Dzp.mjs} +6 -11
  61. package/dist/{delete-BKMOtpjs.mjs → delete-DFmX7jTp.mjs} +6 -11
  62. package/dist/{delete-BMa26SzX.mjs → delete-Ob06PPie.mjs} +6 -11
  63. package/dist/{delete-runtime-_YOukDRC.mjs → delete-runtime-D74s6vhu.mjs} +6 -13
  64. package/dist/{delete-table-D_tjBZPd.mjs → delete-table-DuyhGrvA.mjs} +6 -11
  65. package/dist/{dependencies-BR_4um7h.mjs → dependencies-Bj3QrGIm.mjs} +10 -13
  66. package/dist/dirty-DNYoM6Bp.mjs +31 -0
  67. package/dist/document-BbskZPTT.mjs +19 -0
  68. package/dist/{document-CL4ML5FN.mjs → document-Cd2mmqCp.mjs} +5 -33
  69. package/dist/document-D6OybtP2.mjs +29 -0
  70. package/dist/{eid-DSOk7Khb.mjs → eid-WTZmDdsr.mjs} +12 -54
  71. package/dist/eid-translation-zEHtr5Oc.mjs +35 -0
  72. package/dist/{embedding-CKdw8q7p.mjs → embedding-i-KqpefC.mjs} +2 -4
  73. package/dist/events-Bn7jh5lP.mjs +39 -0
  74. package/dist/export-BjfoZRDJ.mjs +66 -0
  75. package/dist/field-BPsNa-TO.mjs +80 -0
  76. package/dist/{field-DsXTeqBy.mjs → field-Cr2DPUG9.mjs} +2 -81
  77. package/dist/field-Zau6Hc6X.mjs +18 -0
  78. package/dist/fields-CBBa-Prp.mjs +34 -0
  79. package/dist/{get-CHAH_F37.mjs → get-00lyLv6R.mjs} +7 -11
  80. package/dist/{get-T85qZgnv.mjs → get-B7sMgsFs.mjs} +7 -11
  81. package/dist/get-B_xdF1kq.mjs +31 -0
  82. package/dist/{get-DT2MOZ8L.mjs → get-ByBOq30r.mjs} +7 -11
  83. package/dist/get-Bz99dAxK.mjs +35 -0
  84. package/dist/get-C2-Q3iQ5.mjs +31 -0
  85. package/dist/get-CDJFVvhj.mjs +35 -0
  86. package/dist/get-CDMGbgrh.mjs +31 -0
  87. package/dist/get-CnbUCzDM.mjs +31 -0
  88. package/dist/{get-DtvzjfjG.mjs → get-CvI--9S_.mjs} +16 -12
  89. package/dist/{get-CH_JmPc-.mjs → get-DRvsATp-.mjs} +7 -11
  90. package/dist/{get-CgZ5qjQx.mjs → get-DY03Azx9.mjs} +6 -10
  91. package/dist/get-DYO1kywc.mjs +32 -0
  92. package/dist/{get-BSdOE5J4.mjs → get-D_h-G9bn.mjs} +7 -11
  93. package/dist/get-DdsoHaKH.mjs +31 -0
  94. package/dist/{get-DRK5-UdU.mjs → get-DkWO0EI0.mjs} +7 -11
  95. package/dist/{get-43Smv3RI.mjs → get-Dmj9Ygz1.mjs} +7 -17
  96. package/dist/get-DmpB6J9g.mjs +31 -0
  97. package/dist/{get-nZW0W7Ui.mjs → get-Dn9ZiSZr.mjs} +8 -16
  98. package/dist/{get-run-Cwia6e0d.mjs → get-run-Cnux9ln0.mjs} +7 -11
  99. package/dist/git-sync-BDnxPrqU.mjs +104 -0
  100. package/dist/git-sync-DxD_ng48.mjs +136 -0
  101. package/dist/git-sync-MQQYRYLg.mjs +28 -0
  102. package/dist/{group-CILtQqCL.mjs → group-DBM87IgC.mjs} +2 -4
  103. package/dist/has-remote-changes-C684Redh.mjs +35 -0
  104. package/dist/import-Rmmttboo.mjs +56 -0
  105. package/dist/{input-DzbvxKYU.mjs → input-DH9i67x_.mjs} +6 -11
  106. package/dist/{is-dirty-CHbUJ-bh.mjs → is-dirty-DYeJYhBz.mjs} +4 -8
  107. package/dist/{items-DN63mjpF.mjs → items-CQlPXBXE.mjs} +13 -29
  108. package/dist/key-BEhqIzIQ.mjs +10 -0
  109. package/dist/{library-DF2qx50w.mjs → library-Bsm5KsFF.mjs} +6 -9
  110. package/dist/library-ClLgrAXy.mjs +19 -0
  111. package/dist/library-DfYAT2Ep.mjs +21 -0
  112. package/dist/{list-n2PY3OIx.mjs → list-B4hJuMhA.mjs} +11 -27
  113. package/dist/list-B8nAGwP4.mjs +48 -0
  114. package/dist/list-BOET6zhP.mjs +36 -0
  115. package/dist/list-BP3MPq-M.mjs +36 -0
  116. package/dist/list-BpFp9Wre.mjs +28 -0
  117. package/dist/list-BtkWNtvY.mjs +34 -0
  118. package/dist/list-BtmsNOEn.mjs +28 -0
  119. package/dist/list-BzVTHOoH.mjs +28 -0
  120. package/dist/list-C5Zs8nrb.mjs +28 -0
  121. package/dist/list-CKK-s3Ty.mjs +28 -0
  122. package/dist/list-CMpoc2TN.mjs +70 -0
  123. package/dist/list-CNUiF8Z7.mjs +28 -0
  124. package/dist/list-CQDprvW0.mjs +39 -0
  125. package/dist/{list-C7TqbWG1.mjs → list-CQwOgIlj.mjs} +10 -24
  126. package/dist/list-DE9FM957.mjs +28 -0
  127. package/dist/{list-De82cXvn.mjs → list-DF2rvoO1.mjs} +22 -14
  128. package/dist/list-DMKDsBRd.mjs +38 -0
  129. package/dist/{list-B3HoSfYj.mjs → list-UhpKG6_m.mjs} +15 -15
  130. package/dist/{login-jy9rbYev.mjs → login-CGHeSjlP.mjs} +47 -52
  131. package/dist/{logout-CRbk1SuY.mjs → logout-DAxOlbv4.mjs} +7 -12
  132. package/dist/measure-4P0bOlZ3.mjs +29 -0
  133. package/dist/measure-BsYv0p26.mjs +22 -0
  134. package/dist/{measure-S9WszHre.mjs → measure-CtfjqJFP.mjs} +3 -30
  135. package/dist/network-error-CEb9ymDW.mjs +423 -0
  136. package/dist/notification-DaA4bBHW.mjs +138 -0
  137. package/dist/notification-Fcq1fIPw.mjs +67 -0
  138. package/dist/{parameter-BZ6y-Gfs.mjs → parameter-DUKR8NXo.mjs} +2 -11
  139. package/dist/{parameter-values-CcgcG3S5.mjs → parameter-values-CJTdqd8c.mjs} +17 -11
  140. package/dist/{parse-enum-C_2lGr3g.mjs → parse-enum-D0Jfm_Bz.mjs} +2 -4
  141. package/dist/{parse-id-CD54Chc5.mjs → parse-id-C_jmKFaa.mjs} +2 -4
  142. package/dist/{parse-ref-BLgKEEF-.mjs → parse-ref-ibKVB0J4.mjs} +3 -5
  143. package/dist/{path-CPMr1RJO.mjs → path-B5gHvrYL.mjs} +8 -9
  144. package/dist/{poll-DVF9EnEb.mjs → poll-75SvT7Zv.mjs} +11 -15
  145. package/dist/predicates-Bkm2IoeX.mjs +170 -0
  146. package/dist/preflight-YpPQo-sa.mjs +29 -0
  147. package/dist/{process-HDPKLS_z.mjs → process-DBOOrmET.mjs} +4 -6
  148. package/dist/publish-DijrxaCW.mjs +75 -0
  149. package/dist/pulse-BmsDenXm.mjs +133 -0
  150. package/dist/pulse-DhG6I9mI.mjs +57 -0
  151. package/dist/{query-Cxh9hmrP.mjs → query-BbqECzmF.mjs} +20 -44
  152. package/dist/{query-B3HDIsJ-.mjs → query-Dc__-KJH.mjs} +13 -24
  153. package/dist/{query-result-Drvjv7DD.mjs → query-result-DBDwk8TS.mjs} +4 -8
  154. package/dist/remove-collection-BOnxYvhj.mjs +36 -0
  155. package/dist/{render-CkuFkWlQ.mjs → render-CI93iP0I.mjs} +9 -11
  156. package/dist/{replace-BwvKDNur.mjs → replace-Cq4CxVa-.mjs} +7 -12
  157. package/dist/rescan-values-Dr_j416g.mjs +31 -0
  158. package/dist/revision-message-flag-8TCHYJV6.mjs +8 -0
  159. package/dist/run-C3DkS6NP.mjs +82 -0
  160. package/dist/{run-yrpSF6VL.mjs → run-DdGJ544X.mjs} +8 -18
  161. package/dist/runs-CUNWiidL.mjs +38 -0
  162. package/dist/runtime-DiKyBxOw.mjs +1007 -0
  163. package/dist/{schema-tables-ChBYz4mO.mjs → schema-tables-CV386fnC.mjs} +10 -14
  164. package/dist/{schemas-C2crnVML.mjs → schemas-DM-UqZBQ.mjs} +8 -12
  165. package/dist/search-DFBwUc6d.mjs +44 -0
  166. package/dist/{search-DnGEh6sZ.mjs → search-DmGScXs8.mjs} +14 -73
  167. package/dist/segment-BzUGM2Fr.mjs +22 -0
  168. package/dist/segment-C_gl5ag6.mjs +29 -0
  169. package/dist/{segment-BPb1H6DW.mjs → segment-OsrbUDzw.mjs} +3 -30
  170. package/dist/{selectors-Ll_TRxl5.mjs → selectors-DGDn0Hto.mjs} +4 -6
  171. package/dist/send-CVxxEpDB.mjs +49 -0
  172. package/dist/{set-tHsHXRGV.mjs → set-DFolTjbd.mjs} +10 -20
  173. package/dist/{set-active-qqDoBh_Z.mjs → set-active-BD8L1lPX.mjs} +7 -18
  174. package/dist/setting-CwRYgHYN.mjs +35 -0
  175. package/dist/setting-DTiLCW8g.mjs +22 -0
  176. package/dist/setting-DyhaeICs.mjs +17 -0
  177. package/dist/setup-BbDQN8fe.mjs +44 -0
  178. package/dist/setup-CO7QV-ao.mjs +21 -0
  179. package/dist/signal-CMd0EFUa.mjs +16 -0
  180. package/dist/{skills-rnvVgau4.mjs → skills--vK6J-e4.mjs} +4 -6
  181. package/dist/{skills-BKuiGkc1.mjs → skills-DTCrMcix.mjs} +13 -19
  182. package/dist/{snippet-DWiXNy4T.mjs → snippet-CyKAgIZl.mjs} +3 -32
  183. package/dist/snippet-DRwKb2x7.mjs +19 -0
  184. package/dist/snippet-oJLaYW9V.mjs +29 -0
  185. package/dist/stash-D0S4JmAz.mjs +61 -0
  186. package/dist/status-BhswxJL1.mjs +85 -0
  187. package/dist/{status-B5ar0uXc.mjs → status-hL1am-HV.mjs} +6 -8
  188. package/dist/subscription-_d5fB45F.mjs +22 -0
  189. package/dist/subscriptions-s4TF6Ax3.mjs +42 -0
  190. package/dist/summary-BytbDz6e.mjs +7 -0
  191. package/dist/summary-CsPvcUwW.mjs +31 -0
  192. package/dist/sync-schema-DaZ_MV-u.mjs +35 -0
  193. package/dist/sync-task-BACcrs0i.mjs +37 -0
  194. package/dist/{table-C3RIKiYM.mjs → table-CeeTJgQb.mjs} +4 -38
  195. package/dist/table-CsIJNPFf.mjs +37 -0
  196. package/dist/table-DYoC1kPn.mjs +18 -0
  197. package/dist/{timeline-BCTRThc-.mjs → timeline-CCSU2qOS.mjs} +2 -66
  198. package/dist/timeline-event-CNQdCTDg.mjs +19 -0
  199. package/dist/timeline-uDCmwGFT.mjs +66 -0
  200. package/dist/timeline-xlDbEKWg.mjs +21 -0
  201. package/dist/transform-Bs0EWijQ.mjs +28 -0
  202. package/dist/{transform-BVHYzWpK.mjs → transform-D3QX0jxA.mjs} +28 -74
  203. package/dist/transform-DoTyyXAu.mjs +74 -0
  204. package/dist/transform-job-50GZHhKH.mjs +37 -0
  205. package/dist/transform-job-BcLChRup.mjs +22 -0
  206. package/dist/{transform-job-CjsAXMej.mjs → transform-job-DRrK28IH.mjs} +14 -41
  207. package/dist/{transform-tag--IBQ-8Ij.mjs → transform-tag-CcElGp3C.mjs} +2 -21
  208. package/dist/transform-tag-Dmb4u3-Q.mjs +21 -0
  209. package/dist/transform-tag-_tgwlsdB.mjs +18 -0
  210. package/dist/{transforms-CLkv3e81.mjs → transforms-oU4zizbO.mjs} +10 -13
  211. package/dist/{tree-CB2IURsX.mjs → tree-CH-f3bjP.mjs} +6 -10
  212. package/dist/{unpublish-BkZldbkP.mjs → unpublish-BUl9RU5C.mjs} +7 -18
  213. package/dist/{update-B1dkPypu.mjs → update-BCS5FxKr.mjs} +11 -19
  214. package/dist/{update-8bTrglfc.mjs → update-BZPllQoR.mjs} +9 -16
  215. package/dist/{update-BacyVaLu.mjs → update-BiFDBcEH.mjs} +9 -16
  216. package/dist/update-BzMDeZiU.mjs +50 -0
  217. package/dist/{update-B4atxTx0.mjs → update-C4YJQFDS.mjs} +9 -16
  218. package/dist/{update-CGWTX1Z0.mjs → update-CHNSUHK4.mjs} +9 -16
  219. package/dist/{update-D7Ia9Qrt.mjs → update-CO4m4wH3.mjs} +10 -21
  220. package/dist/{update-CO9uCJxV.mjs → update-CVPAwJaH.mjs} +10 -18
  221. package/dist/{update-BHC3pwzR.mjs → update-CmDTljK-.mjs} +9 -16
  222. package/dist/{update-iY9WZqy0.mjs → update-CvOO8TED.mjs} +9 -17
  223. package/dist/{update-Cyxjg496.mjs → update-D-NE60AV.mjs} +9 -16
  224. package/dist/{update-D80GWpWl.mjs → update-Nfi44RrE.mjs} +10 -18
  225. package/dist/update-bD_Jh5-s.mjs +51 -0
  226. package/dist/{update-DajyWtBN.mjs → update-cYkvbqK8.mjs} +9 -16
  227. package/dist/update-dashcard-C3TuYO_k.mjs +50 -0
  228. package/dist/{update-BghbOcv6.mjs → update-tX9mKBN_.mjs} +10 -21
  229. package/dist/{upgrade-CXoNQ4FH.mjs → upgrade-DXMV4AyP.mjs} +37 -44
  230. package/dist/upload-CH632qW6.mjs +46 -0
  231. package/dist/upload-DAtxBBms.mjs +13 -0
  232. package/dist/upload-Dey_8rLf.mjs +13 -0
  233. package/dist/{uuid-D6dao_q4.mjs → uuid-BJkDWj9p.mjs} +5 -7
  234. package/dist/validate-BWchyW0V.mjs +1469 -0
  235. package/dist/{validate-query-D1N30wJ7.mjs → validate-query-DaGYSmpQ.mjs} +4 -5
  236. package/dist/{values-DIBAgSyz.mjs → values-Dxf1JEoA.mjs} +8 -13
  237. package/dist/verify-K96rItG5.mjs +89 -0
  238. package/dist/{wait-CW1OawkI.mjs → wait-DoMDH226.mjs} +10 -18
  239. package/dist/{wait-flags-DvNU8ahZ.mjs → wait-flags-DWEF9tX4.mjs} +14 -11
  240. package/dist/window-BkvrP0gB.mjs +64 -0
  241. package/package.json +5 -35
  242. package/skill-data/core/SKILL.md +31 -26
  243. package/skill-data/dashboard/SKILL.md +6 -2
  244. package/skill-data/document/SKILL.md +2 -2
  245. package/skill-data/git-sync/SKILL.md +20 -5
  246. package/skill-data/notification/SKILL.md +157 -0
  247. package/skill-data/transform/SKILL.md +1 -1
  248. package/.claude-plugin/marketplace.json +0 -19
  249. package/dist/add-collection-C8ZTPlIE.mjs +0 -9
  250. package/dist/add-collection-CUBn11d4.mjs +0 -60
  251. package/dist/auth-hgAnMUfi.mjs +0 -22
  252. package/dist/capabilities-DOTcPraV.mjs +0 -684
  253. package/dist/card-Ct-q_C4S.mjs +0 -26
  254. package/dist/cards-CYSyvN7Z.mjs +0 -38
  255. package/dist/cli.d.mts +0 -1
  256. package/dist/collection-K82kJWdj.mjs +0 -23
  257. package/dist/command-augment-D9pI9Vbh.mjs +0 -11
  258. package/dist/create-branch-DPE6itiS.mjs +0 -57
  259. package/dist/dashboard-B1iRSUBI.mjs +0 -35
  260. package/dist/database-CIbVSfua.mjs +0 -61
  261. package/dist/db-eWy7A-H3.mjs +0 -27
  262. package/dist/dirty-BKCg6oVN.mjs +0 -35
  263. package/dist/document-CVxhTnUD.mjs +0 -22
  264. package/dist/events-Dxm7me47.mjs +0 -44
  265. package/dist/export-Gb_wfZpt.mjs +0 -103
  266. package/dist/field-BTCw6voJ.mjs +0 -21
  267. package/dist/fields-hZeq6IF2.mjs +0 -37
  268. package/dist/get--rGDVyje.mjs +0 -35
  269. package/dist/get-7Np_G2je.mjs +0 -35
  270. package/dist/get-CP3lrIYi.mjs +0 -49
  271. package/dist/get-CuPCE_AG.mjs +0 -35
  272. package/dist/get-DB6Y9igl.mjs +0 -41
  273. package/dist/get-DWzMR8sn.mjs +0 -35
  274. package/dist/get-DZatHVdn.mjs +0 -38
  275. package/dist/git-sync-Cjrx2meo.mjs +0 -31
  276. package/dist/has-remote-changes-CIIib71u.mjs +0 -67
  277. package/dist/import-D9ID9Mz4.mjs +0 -94
  278. package/dist/is-dirty-DY5Zhsbk.mjs +0 -8
  279. package/dist/key-BnGRTX8U.mjs +0 -17
  280. package/dist/list-B1sdMz6m.mjs +0 -31
  281. package/dist/list-BSxMFDMR.mjs +0 -31
  282. package/dist/list-BeqcZVSn.mjs +0 -39
  283. package/dist/list-C0344yqi.mjs +0 -52
  284. package/dist/list-C5Ir-96z.mjs +0 -49
  285. package/dist/list-C6YpaUpC.mjs +0 -39
  286. package/dist/list-CQN2BpaW.mjs +0 -31
  287. package/dist/list-CY-jpBNE.mjs +0 -31
  288. package/dist/list-CkTsOOA7.mjs +0 -39
  289. package/dist/list-CvS68tLn.mjs +0 -31
  290. package/dist/list-KDHLmoUx.mjs +0 -31
  291. package/dist/list-MqqHcBvD.mjs +0 -31
  292. package/dist/measure-CPqisgyf.mjs +0 -25
  293. package/dist/paginate-CMqbqhMC.mjs +0 -49
  294. package/dist/poll-task-CpHGQOd5.mjs +0 -194
  295. package/dist/preflight-xhwEOHAt.mjs +0 -90
  296. package/dist/prompt-BgkWNgIR.mjs +0 -52
  297. package/dist/publish-xVPABwE8.mjs +0 -65
  298. package/dist/remove-collection-_a4uIlLB.mjs +0 -42
  299. package/dist/requests-qyh002pL.mjs +0 -96
  300. package/dist/rescan-values-Bd0Joerq.mjs +0 -40
  301. package/dist/resolve-Ct084wx3.mjs +0 -84
  302. package/dist/revision-message-flag-CHzX0cqV.mjs +0 -11
  303. package/dist/run-BfpKUjqL.mjs +0 -135
  304. package/dist/runs-D_08Ma08.mjs +0 -53
  305. package/dist/runtime-Ab96yYlM.mjs +0 -1695
  306. package/dist/segment-DyVTZSIM.mjs +0 -25
  307. package/dist/setting-B9xSyMf6.mjs +0 -20
  308. package/dist/setting-Cko6bE_w.mjs +0 -55
  309. package/dist/setup-CXGcyTuv.mjs +0 -71
  310. package/dist/snippet-C4h-GMUf.mjs +0 -22
  311. package/dist/stash-DxmpBS7x.mjs +0 -108
  312. package/dist/status-D5CR1SrS.mjs +0 -69
  313. package/dist/summary-BEEJl2O1.mjs +0 -40
  314. package/dist/sync-schema-B5HDpmrp.mjs +0 -54
  315. package/dist/table-DHmaW3Ec.mjs +0 -21
  316. package/dist/timeline-B0R6-dm8.mjs +0 -24
  317. package/dist/timeline-event-BVDTt-pM.mjs +0 -22
  318. package/dist/transform-Cq2_muWO.mjs +0 -31
  319. package/dist/transform-job-BpebgMnq.mjs +0 -25
  320. package/dist/transform-tag-B1xnFa9w.mjs +0 -21
  321. package/dist/update-dashcard-DLq7ihNO.mjs +0 -73
  322. package/dist/upload-D3eiApa0.mjs +0 -16
  323. package/dist/validate-Cqa14t7o.mjs +0 -1496
  324. package/dist/verify-DvhZWmS2.mjs +0 -79
@@ -1,1695 +0,0 @@
1
- import { AbortError, BASELINE_CAPABILITIES, ConfigError, DEFAULT_MAX_BYTES, ENV_API_KEY, ENV_DISABLE_KEYRING, ENV_PROFILE, ENV_SKIP_PREFLIGHT, ENV_URL, MetabaseError, NetworkError, ResponseShapeError, TimeoutError, ValidationError, consumeLegacyEnvWarnings, errorMessage, flagConsumesValue, isNotFoundError, isPlainObject, normalizeFlag, package_default, readEnv, reportError, toAliasArray, warn } from "./capabilities-DOTcPraV.mjs";
2
- import { setMetabaseAugment } from "./command-augment-D9pI9Vbh.mjs";
3
- import { defineCommand } from "citty";
4
- import { z } from "zod";
5
- import { promises } from "node:fs";
6
- import { dirname, join } from "node:path";
7
- import { Entry } from "@napi-rs/keyring";
8
- import { homedir } from "node:os";
9
- import { parse } from "semver";
10
- import { setTimeout } from "node:timers/promises";
11
-
12
- //#region src/runtime/json.ts
13
- const JSON_CONTENT_TYPE = "application/json";
14
- function parseJson(input, schema, opts = {}) {
15
- const result = parseJsonResult(input, schema, opts);
16
- if (!result.ok) throw result.error;
17
- return result.value;
18
- }
19
- function parseJsonResult(input, schema, opts = {}) {
20
- const sourcePrefix = opts.source ? `${opts.source}: ` : "";
21
- let raw;
22
- try {
23
- raw = JSON.parse(input);
24
- } catch (error) {
25
- return {
26
- ok: false,
27
- error: new ConfigError(`${sourcePrefix}invalid JSON: ${errorMessage(error)}`)
28
- };
29
- }
30
- const parsed = schema.safeParse(raw);
31
- if (!parsed.success) return {
32
- ok: false,
33
- error: new ValidationError(`${sourcePrefix}value did not match expected schema`, {
34
- source: opts.source ?? "<input>",
35
- zodIssues: parsed.error.issues
36
- })
37
- };
38
- return {
39
- ok: true,
40
- value: parsed.data
41
- };
42
- }
43
- function parseJsonOrPlain(text, contentType, schema, opts = {}) {
44
- if (!isJsonContentType(contentType)) return parseJson(JSON.stringify(text), schema, opts);
45
- const attempt = parseJsonResult(text, schema, opts);
46
- if (attempt.ok) return attempt.value;
47
- if (attempt.error instanceof ValidationError) throw attempt.error;
48
- return parseJson(JSON.stringify(text), schema, opts);
49
- }
50
- function isJsonContentType(contentType) {
51
- return contentType !== null && contentType.includes(JSON_CONTENT_TYPE);
52
- }
53
-
54
- //#endregion
55
- //#region src/core/paths.ts
56
- const APP_DIR_NAME = "metabase-cli";
57
- function configDir() {
58
- if (process.platform === "win32") {
59
- const appData = process.env["APPDATA"] ?? join(homedir(), "AppData", "Roaming");
60
- return join(appData, APP_DIR_NAME);
61
- }
62
- const xdg = process.env["XDG_CONFIG_HOME"] ?? join(homedir(), ".config");
63
- return join(xdg, APP_DIR_NAME);
64
- }
65
-
66
- //#endregion
67
- //#region src/domain/session-properties.ts
68
- const ServerVersion = z.object({
69
- tag: z.string(),
70
- date: z.string().optional(),
71
- hash: z.string().optional()
72
- }).loose();
73
- const TokenFeatures = z.record(z.string(), z.boolean());
74
- const SessionProperties = z.object({
75
- version: ServerVersion,
76
- "token-features": TokenFeatures.optional()
77
- }).loose();
78
-
79
- //#endregion
80
- //#region src/core/version/tag.ts
81
- const ParsedVersionSchema = z.object({
82
- tag: z.string(),
83
- major: z.number().int().nonnegative(),
84
- patch: z.number().int().nonnegative()
85
- });
86
- function tryParseTag(tag) {
87
- const parsed = parse(tag);
88
- if (parsed === null || parsed.major !== 0 && parsed.major !== 1) return null;
89
- return {
90
- tag,
91
- major: parsed.minor,
92
- patch: parsed.patch
93
- };
94
- }
95
-
96
- //#endregion
97
- //#region src/core/auth/profile-record.ts
98
- const ProbedUser = z.object({
99
- id: z.number().int(),
100
- name: z.string(),
101
- isAdmin: z.boolean()
102
- });
103
- const ProfileLastProbe = z.object({
104
- at: z.iso.datetime(),
105
- version: ParsedVersionSchema.nullable(),
106
- tokenFeatures: TokenFeatures.nullable(),
107
- user: ProbedUser
108
- });
109
- const ProfileFailureKind = z.enum([
110
- "auth",
111
- "network",
112
- "server"
113
- ]);
114
- const ProfileLastFailure = z.object({
115
- at: z.iso.datetime(),
116
- kind: ProfileFailureKind,
117
- reason: z.string()
118
- });
119
- const ProfileOAuth = z.object({
120
- accessToken: z.string().nullable(),
121
- refreshToken: z.string().nullable(),
122
- expiresAt: z.iso.datetime(),
123
- clientId: z.string()
124
- }).loose();
125
- const ProfileAuthMethod = z.enum(["oauth", "apiKey"]);
126
- const ProfileRecord = z.object({
127
- name: z.string(),
128
- url: z.string(),
129
- apiKey: z.string().nullable(),
130
- oauth: ProfileOAuth.nullable().default(null),
131
- lastProbe: ProfileLastProbe.nullable(),
132
- lastFailure: ProfileLastFailure.nullable()
133
- }).loose();
134
- const ProfilesFile = z.object({ profiles: z.array(ProfileRecord) }).loose();
135
- function profileAuthMethod(record) {
136
- return record.oauth !== null ? "oauth" : "apiKey";
137
- }
138
-
139
- //#endregion
140
- //#region src/core/auth/storage.ts
141
- const KEYRING_SERVICE = "metabase-cli";
142
- const PROFILES_FILE = "profiles.json";
143
- const LEGACY_CREDENTIALS_FILE = "credentials.json";
144
- const LEGACY_REJECTIONS_FILE = "rejections.json";
145
- const PROFILES_FILE_MODE = 384;
146
- const PROFILES_DIR_MODE = 448;
147
- const DEFAULT_PROFILE = "default";
148
- const LEGACY_STORAGE_NOTICE = "Old profile storage detected and ignored; re-run `mb auth login` for each profile.";
149
- const KEYCHAIN_RESIDUAL_NOTICE = "warning: could not remove one or more secrets from the OS keychain; a stored token may remain — remove it manually or retry.";
150
- const account = {
151
- profileApiKey: (profile) => `profile:${profile}:apiKey`,
152
- profileOAuthAccess: (profile) => `profile:${profile}:oauthAccess`,
153
- profileOAuthRefresh: (profile) => `profile:${profile}:oauthRefresh`
154
- };
155
- let legacyWarningPending = false;
156
- let keychainResidualPending = false;
157
- let keyringDowngradeNotice = null;
158
- function profilesFilePath() {
159
- return join(configDir(), PROFILES_FILE);
160
- }
161
- function consumeLegacyStorageWarning() {
162
- if (!legacyWarningPending) return null;
163
- legacyWarningPending = false;
164
- return LEGACY_STORAGE_NOTICE;
165
- }
166
- function consumeKeychainResidualWarning() {
167
- if (!keychainResidualPending) return null;
168
- keychainResidualPending = false;
169
- return KEYCHAIN_RESIDUAL_NOTICE;
170
- }
171
- function consumeKeyringDowngradeWarning() {
172
- const message = keyringDowngradeNotice;
173
- keyringDowngradeNotice = null;
174
- return message;
175
- }
176
- function keyringEnabled() {
177
- return readEnv(ENV_DISABLE_KEYRING) !== "1";
178
- }
179
- function trySetKeyring(key, value) {
180
- if (!keyringEnabled()) return false;
181
- try {
182
- new Entry(KEYRING_SERVICE, key).setPassword(value);
183
- return true;
184
- } catch {
185
- return false;
186
- }
187
- }
188
- function tryReadKeyring(key) {
189
- if (!keyringEnabled()) return void 0;
190
- try {
191
- return new Entry(KEYRING_SERVICE, key).getPassword();
192
- } catch {
193
- return void 0;
194
- }
195
- }
196
- function removeKeyringEntry(key) {
197
- if (!keyringEnabled()) return "skipped";
198
- try {
199
- return new Entry(KEYRING_SERVICE, key).deletePassword() ? "removed" : "absent";
200
- } catch {
201
- return "failed";
202
- }
203
- }
204
- async function readProfilesFile() {
205
- const path = profilesFilePath();
206
- let raw;
207
- try {
208
- raw = await promises.readFile(path, "utf8");
209
- } catch (error) {
210
- if (isNotFoundError(error)) {
211
- await detectLegacyArtifacts();
212
- return { profiles: [] };
213
- }
214
- throw error;
215
- }
216
- const parsed = parseJsonResult(raw, ProfilesFile, { source: path });
217
- if (parsed.ok) return parsed.value;
218
- if (parsed.error instanceof ValidationError) {
219
- legacyWarningPending = true;
220
- return { profiles: [] };
221
- }
222
- throw parsed.error;
223
- }
224
- async function detectLegacyArtifacts() {
225
- const legacyCredentials = join(configDir(), LEGACY_CREDENTIALS_FILE);
226
- const legacyRejections = join(configDir(), LEGACY_REJECTIONS_FILE);
227
- const [credentialsExists, rejectionsExists] = await Promise.all([fileExists(legacyCredentials), fileExists(legacyRejections)]);
228
- if (credentialsExists || rejectionsExists) legacyWarningPending = true;
229
- }
230
- async function fileExists(path) {
231
- try {
232
- await promises.access(path);
233
- return true;
234
- } catch {
235
- return false;
236
- }
237
- }
238
- async function writeProfilesFile(file) {
239
- const path = profilesFilePath();
240
- if (file.profiles.length === 0) {
241
- await promises.unlink(path).catch(() => void 0);
242
- await cleanupLegacyFiles();
243
- return;
244
- }
245
- await promises.mkdir(dirname(path), {
246
- recursive: true,
247
- mode: PROFILES_DIR_MODE
248
- });
249
- const tmpPath = `${path}.${process.pid}.tmp`;
250
- await promises.writeFile(tmpPath, JSON.stringify(file, null, 2) + "\n", { mode: PROFILES_FILE_MODE });
251
- if (process.platform !== "win32") await promises.chmod(tmpPath, PROFILES_FILE_MODE);
252
- try {
253
- await promises.rename(tmpPath, path);
254
- } catch (error) {
255
- await promises.unlink(tmpPath).catch(() => void 0);
256
- throw error;
257
- }
258
- await cleanupLegacyFiles();
259
- }
260
- async function cleanupLegacyFiles() {
261
- await Promise.all([promises.unlink(join(configDir(), LEGACY_CREDENTIALS_FILE)).catch(() => void 0), promises.unlink(join(configDir(), LEGACY_REJECTIONS_FILE)).catch(() => void 0)]);
262
- }
263
- function findRecord(file, name) {
264
- return file.profiles.find((entry) => entry.name === name) ?? null;
265
- }
266
- function sideIsKeyringBacked(record, side) {
267
- return side === "oauth" ? record.oauth !== null && record.oauth.accessToken === null : record.oauth === null && record.apiKey === null;
268
- }
269
- function flagResidualIfUnconfirmed(existing, cleared, removals) {
270
- if (existing === null || !removals.includes("failed")) return;
271
- if (sideIsKeyringBacked(existing, cleared)) keychainResidualPending = true;
272
- }
273
- function fileLocation(key) {
274
- return {
275
- backend: "file",
276
- path: profilesFilePath(),
277
- account: key,
278
- reason: keyringEnabled() ? "unavailable" : "disabled"
279
- };
280
- }
281
- function keyringFallbackWarning(location) {
282
- const cause = location.reason === "disabled" ? `OS keychain disabled via ${ENV_DISABLE_KEYRING}` : "OS keychain unavailable";
283
- return `warning: ${cause}; credentials stored as plaintext at ${location.path}`;
284
- }
285
- function persistSecret(key, value) {
286
- if (trySetKeyring(key, value)) return {
287
- backend: "keyring",
288
- service: KEYRING_SERVICE,
289
- account: key
290
- };
291
- removeKeyringEntry(key);
292
- return fileLocation(key);
293
- }
294
- function resolveSecret(key, inline) {
295
- if (inline !== null) return inline;
296
- return tryReadKeyring(key) ?? null;
297
- }
298
- async function readProfileCredential(name = DEFAULT_PROFILE) {
299
- const file = await readProfilesFile();
300
- const record = findRecord(file, name);
301
- if (record === null) return null;
302
- return resolveRecordCredential(record);
303
- }
304
- function resolveRecordCredential(record) {
305
- if (record.oauth !== null) {
306
- const accessToken = resolveSecret(account.profileOAuthAccess(record.name), record.oauth.accessToken);
307
- const refreshToken = resolveSecret(account.profileOAuthRefresh(record.name), record.oauth.refreshToken);
308
- if (accessToken === null || refreshToken === null) return null;
309
- return {
310
- url: record.url,
311
- credential: {
312
- kind: "oauth",
313
- accessToken,
314
- refreshToken,
315
- expiresAt: record.oauth.expiresAt,
316
- clientId: record.oauth.clientId
317
- }
318
- };
319
- }
320
- const apiKey = resolveSecret(account.profileApiKey(record.name), record.apiKey);
321
- if (apiKey === null) return null;
322
- return {
323
- url: record.url,
324
- credential: {
325
- kind: "apiKey",
326
- apiKey
327
- }
328
- };
329
- }
330
- async function readProfileRecord(name = DEFAULT_PROFILE) {
331
- const file = await readProfilesFile();
332
- return findRecord(file, name);
333
- }
334
- async function listProfileRecords() {
335
- const file = await readProfilesFile();
336
- return file.profiles;
337
- }
338
- async function upsertRecord(file, name, updated) {
339
- const exists = findRecord(file, name) !== null;
340
- const profiles = exists ? file.profiles.map((entry) => entry.name === name ? updated : entry) : [...file.profiles, updated];
341
- await writeProfilesFile({
342
- ...file,
343
- profiles
344
- });
345
- }
346
- async function writeProfile(profile, name = DEFAULT_PROFILE) {
347
- const location = persistSecret(account.profileApiKey(name), profile.apiKey);
348
- const inlineApiKey = location.backend === "file" ? profile.apiKey : null;
349
- const file = await readProfilesFile();
350
- const existing = findRecord(file, name);
351
- flagResidualIfUnconfirmed(existing, "oauth", [removeKeyringEntry(account.profileOAuthAccess(name)), removeKeyringEntry(account.profileOAuthRefresh(name))]);
352
- const updated = existing === null ? {
353
- name,
354
- url: profile.url,
355
- apiKey: inlineApiKey,
356
- oauth: null,
357
- lastProbe: null,
358
- lastFailure: null
359
- } : {
360
- ...existing,
361
- url: profile.url,
362
- apiKey: inlineApiKey,
363
- oauth: null
364
- };
365
- await upsertRecord(file, name, updated);
366
- return location;
367
- }
368
- async function writeOAuthProfile(url, credential, name = DEFAULT_PROFILE) {
369
- const accessKey = account.profileOAuthAccess(name);
370
- const refreshKey = account.profileOAuthRefresh(name);
371
- const accessLocation = persistSecret(accessKey, credential.accessToken);
372
- const refreshLocation = persistSecret(refreshKey, credential.refreshToken);
373
- const onFile = accessLocation.backend === "file" || refreshLocation.backend === "file";
374
- const oauth = {
375
- accessToken: onFile ? credential.accessToken : null,
376
- refreshToken: onFile ? credential.refreshToken : null,
377
- expiresAt: credential.expiresAt,
378
- clientId: credential.clientId
379
- };
380
- const file = await readProfilesFile();
381
- const existing = findRecord(file, name);
382
- if (onFile && existing !== null && sideIsKeyringBacked(existing, "oauth")) keyringDowngradeNotice = keyringFallbackWarning(fileLocation(accessKey));
383
- flagResidualIfUnconfirmed(existing, "apiKey", [removeKeyringEntry(account.profileApiKey(name))]);
384
- const updated = existing === null ? {
385
- name,
386
- url,
387
- apiKey: null,
388
- oauth,
389
- lastProbe: null,
390
- lastFailure: null
391
- } : {
392
- ...existing,
393
- url,
394
- apiKey: null,
395
- oauth
396
- };
397
- await upsertRecord(file, name, updated);
398
- return onFile ? fileLocation(accessKey) : {
399
- backend: "keyring",
400
- service: KEYRING_SERVICE,
401
- account: accessKey
402
- };
403
- }
404
- async function writeProbeResult(name, input) {
405
- const probe = ProfileLastProbe.parse({
406
- at: new Date().toISOString(),
407
- version: input.server.version,
408
- tokenFeatures: input.server.tokenFeatures,
409
- user: input.user
410
- });
411
- const file = await readProfilesFile();
412
- const existing = findRecord(file, name);
413
- if (existing === null) return null;
414
- const profiles = file.profiles.map((entry) => entry.name === name ? {
415
- ...entry,
416
- lastProbe: probe,
417
- lastFailure: null
418
- } : entry);
419
- await writeProfilesFile({
420
- ...file,
421
- profiles
422
- });
423
- return probe;
424
- }
425
- async function writeProbeFailure(name, input) {
426
- const failure$1 = ProfileLastFailure.parse({
427
- at: new Date().toISOString(),
428
- kind: input.kind,
429
- reason: input.reason
430
- });
431
- const file = await readProfilesFile();
432
- const existing = findRecord(file, name);
433
- if (existing === null) return null;
434
- const profiles = file.profiles.map((entry) => entry.name === name ? {
435
- ...entry,
436
- lastFailure: failure$1
437
- } : entry);
438
- await writeProfilesFile({
439
- ...file,
440
- profiles
441
- });
442
- return failure$1;
443
- }
444
- async function clearProfile(name = DEFAULT_PROFILE) {
445
- const file = await readProfilesFile();
446
- const existing = findRecord(file, name);
447
- const removals = [
448
- removeKeyringEntry(account.profileApiKey(name)),
449
- removeKeyringEntry(account.profileOAuthAccess(name)),
450
- removeKeyringEntry(account.profileOAuthRefresh(name))
451
- ];
452
- if (existing !== null) flagResidualIfUnconfirmed(existing, existing.oauth !== null ? "oauth" : "apiKey", removals);
453
- if (existing === null) return false;
454
- await writeProfilesFile({
455
- ...file,
456
- profiles: file.profiles.filter((entry) => entry.name !== name)
457
- });
458
- return true;
459
- }
460
-
461
- //#endregion
462
- //#region src/runtime/signal.ts
463
- function createProcessAbortHandler() {
464
- const controller = new AbortController();
465
- const handler = () => {
466
- if (!controller.signal.aborted) controller.abort(new AbortError("interrupted"));
467
- process.off("SIGINT", handler);
468
- };
469
- process.on("SIGINT", handler);
470
- return {
471
- signal: controller.signal,
472
- uninstall: () => process.off("SIGINT", handler)
473
- };
474
- }
475
- let singleton = null;
476
- function getProcessAbortSignal() {
477
- if (singleton === null) singleton = createProcessAbortHandler().signal;
478
- return singleton;
479
- }
480
- function combineAborts(timeoutSignal, callerSignal) {
481
- const processSignal = getProcessAbortSignal();
482
- const signals = [timeoutSignal, processSignal];
483
- if (callerSignal) signals.push(callerSignal);
484
- return {
485
- combined: AbortSignal.any(signals),
486
- processSignal
487
- };
488
- }
489
- function throwIfAborted(...signals) {
490
- for (const signal of signals) if (signal?.aborted) throw abortReason(signal);
491
- }
492
- function abortReason(signal) {
493
- const reason = signal.reason;
494
- if (reason instanceof MetabaseError) return reason;
495
- if (reason instanceof Error || typeof reason === "string") return new AbortError(errorMessage(reason) || "aborted");
496
- return new AbortError("aborted");
497
- }
498
-
499
- //#endregion
500
- //#region src/core/auth/credential.ts
501
- const API_KEY_HEADER = "x-api-key";
502
- const AUTHORIZATION_HEADER = "authorization";
503
- const BEARER_PREFIX = "Bearer ";
504
- const EXPIRY_SKEW_MS = 6e4;
505
- const DEFAULT_EXPIRES_IN_SECONDS = 3600;
506
- function credentialAuthHeader(credential) {
507
- if (credential.kind === "apiKey") return {
508
- name: API_KEY_HEADER,
509
- value: credential.apiKey
510
- };
511
- return {
512
- name: AUTHORIZATION_HEADER,
513
- value: BEARER_PREFIX + credential.accessToken
514
- };
515
- }
516
- function credentialSecrets(credential) {
517
- if (credential.kind === "apiKey") return [credential.apiKey];
518
- return [credential.accessToken, credential.refreshToken];
519
- }
520
- function isOAuthExpired(credential, nowMs) {
521
- const expiryMs = Date.parse(credential.expiresAt);
522
- if (Number.isNaN(expiryMs)) return true;
523
- return expiryMs - EXPIRY_SKEW_MS <= nowMs;
524
- }
525
- function expiresAtFromNow(expiresInSeconds, nowMs) {
526
- return new Date(nowMs + expiresInSeconds * 1e3).toISOString();
527
- }
528
- function oauthCredentialFromTokens(tokens, refreshToken, clientId, nowMs) {
529
- return {
530
- kind: "oauth",
531
- accessToken: tokens.access_token,
532
- refreshToken,
533
- expiresAt: expiresAtFromNow(tokens.expires_in ?? DEFAULT_EXPIRES_IN_SECONDS, nowMs),
534
- clientId
535
- };
536
- }
537
-
538
- //#endregion
539
- //#region src/core/http/sanitize.ts
540
- const SECRET_HEADER_NAMES = new Set([
541
- "authorization",
542
- "x-api-key",
543
- "x-metabase-session",
544
- "cookie",
545
- "set-cookie",
546
- "proxy-authorization"
547
- ]);
548
- const REDACTED = "[REDACTED]";
549
- function redactHeaders(headers) {
550
- const result = {};
551
- const entries = headers instanceof Headers ? headers.entries() : Object.entries(headers);
552
- for (const [key, value] of entries) result[key] = SECRET_HEADER_NAMES.has(key.toLowerCase()) ? REDACTED : value;
553
- return result;
554
- }
555
- function redactBody(body, ctx) {
556
- let result = body;
557
- for (const secret of ctx.knownSecrets) {
558
- if (secret.length === 0) continue;
559
- result = result.replaceAll(secret, REDACTED);
560
- }
561
- return result;
562
- }
563
-
564
- //#endregion
565
- //#region src/core/http/errors.ts
566
- const ROUTE_MISSING_LITERAL = "API endpoint does not exist.";
567
- const RESOURCE_MISSING_LITERAL = "Not found.";
568
- const STATUS_CLASSIFICATIONS = {
569
- 401: { retryable: false },
570
- 403: { retryable: false },
571
- 404: { retryable: false },
572
- 408: {
573
- retryable: true,
574
- message: "Metabase timed out responding."
575
- },
576
- 425: { retryable: true },
577
- 429: {
578
- retryable: true,
579
- message: "Metabase rate-limited the request."
580
- },
581
- 500: { retryable: true },
582
- 502: { retryable: true },
583
- 503: { retryable: true },
584
- 504: {
585
- retryable: true,
586
- message: "Metabase timed out responding."
587
- }
588
- };
589
- const ErrorEnvelope = z.object({
590
- message: z.string().optional(),
591
- error: z.string().optional(),
592
- "error-message": z.string().optional(),
593
- via: z.array(z.object({ message: z.string().optional() }).loose()).optional(),
594
- "specific-errors": z.unknown().optional(),
595
- errors: z.unknown().optional()
596
- }).loose();
597
- const MAX_EXTRACTED_MESSAGE_LEN = 500;
598
- const ELLIPSIS = "…";
599
- var HttpError = class extends MetabaseError {
600
- category = "http";
601
- exitCode = 1;
602
- status;
603
- kind;
604
- developerDetail;
605
- constructor(input) {
606
- const sanitizedBody = sanitizeBody(input.rawBody, input.redactionContext);
607
- const redactedHeaders = redactHeaders(input.responseHeaders);
608
- const kind = classifyKind(input.status, sanitizedBody, redactedHeaders);
609
- super(input.overrideUserMessage ?? buildUserMessage(kind, input, sanitizedBody));
610
- this.name = "HttpError";
611
- this.status = input.status;
612
- this.kind = kind;
613
- this.developerDetail = {
614
- status: input.status,
615
- statusText: input.statusText,
616
- method: input.method,
617
- url: input.url,
618
- responseHeaders: redactedHeaders,
619
- body: sanitizedBody
620
- };
621
- }
622
- get isRetryable() {
623
- return isRetryableStatus(this.status);
624
- }
625
- };
626
- function isRetryableStatus(status) {
627
- return STATUS_CLASSIFICATIONS[status]?.retryable === true;
628
- }
629
- function sanitizeBody(rawBody, ctx) {
630
- if (rawBody === null) return null;
631
- if (ctx === void 0) return rawBody;
632
- return redactBody(rawBody, ctx);
633
- }
634
- function classifyKind(status, sanitizedBody, redactedHeaders) {
635
- if (status === 401 || status === 403) return "auth";
636
- if (status === 404) return isRouteMissingResponse(sanitizedBody, redactedHeaders) ? "route-missing" : "resource-missing";
637
- if (status === 429) return "rate-limit";
638
- if (status >= 500 && status < 600) return "server-error";
639
- return "generic";
640
- }
641
- function isRouteMissingResponse(sanitizedBody, redactedHeaders) {
642
- if (sanitizedBody?.includes(ROUTE_MISSING_LITERAL)) return true;
643
- if (sanitizedBody?.includes(RESOURCE_MISSING_LITERAL)) return false;
644
- if (redactedHeaders["content-type"]?.includes(JSON_CONTENT_TYPE)) return false;
645
- if (sanitizedBody === null || sanitizedBody.trim() === "") return true;
646
- return !parseJsonResult(sanitizedBody, ErrorEnvelope).ok;
647
- }
648
- function buildUserMessage(kind, input, sanitizedBody) {
649
- if (kind === "route-missing") return buildRouteMissingMessage(input);
650
- if (kind === "resource-missing") return `Not found: ${input.method} ${pathFromUrl(input.url)}.`;
651
- const fromBody = parseEnvelopeMessage(sanitizedBody);
652
- if (fromBody !== null) return fromBody;
653
- if (kind === "auth") return `Invalid or unauthorized API key (host: ${hostFromUrl(input.url)}).`;
654
- return defaultMessageForStatus(input.status);
655
- }
656
- function buildRouteMissingMessage(input) {
657
- const path = pathFromUrl(input.url);
658
- if (!input.serverTag) return `This endpoint is not available on the connected Metabase: ${input.method} ${path}.`;
659
- return `This endpoint is not available on Metabase ${input.serverTag}: ${input.method} ${path}. The command may require a newer Metabase major version. Run 'mb auth list' to see this server's version.`;
660
- }
661
- function pathFromUrl(url) {
662
- const parsed = new URL(url);
663
- return parsed.pathname + parsed.search;
664
- }
665
- function hostFromUrl(url) {
666
- return new URL(url).host;
667
- }
668
- function parseEnvelopeMessage(sanitizedBody) {
669
- if (!sanitizedBody) return null;
670
- const result = parseJsonResult(sanitizedBody, ErrorEnvelope);
671
- if (!result.ok) return null;
672
- const envelope = result.value;
673
- const topLevel = envelope.message ?? envelope.error ?? envelope["error-message"];
674
- if (topLevel) return capLength(topLevel);
675
- const viaMessage = envelope.via?.find((entry) => entry.message)?.message;
676
- if (viaMessage) return capLength(viaMessage);
677
- const specific = formatErrorTree(envelope["specific-errors"]);
678
- if (specific) return capLength(specific);
679
- const generic = formatErrorTree(envelope.errors);
680
- if (generic) return capLength(generic);
681
- return null;
682
- }
683
- function formatErrorTree(value) {
684
- const entries = collectLeafEntries(value, []);
685
- if (entries.length === 0) return null;
686
- return entries.map(formatLeafEntry).join("; ");
687
- }
688
- function formatLeafEntry(entry) {
689
- return entry.path === "" ? entry.message : `${entry.path}: ${entry.message}`;
690
- }
691
- function collectLeafEntries(value, path) {
692
- if (typeof value === "string") {
693
- const trimmed = value.trim();
694
- return trimmed === "" ? [] : [{
695
- path: path.join("."),
696
- message: trimmed
697
- }];
698
- }
699
- if (Array.isArray(value)) {
700
- const messages = value.filter((entry) => typeof entry === "string" && entry.trim() !== "");
701
- if (messages.length === 0) return [];
702
- return [{
703
- path: path.join("."),
704
- message: messages.join("; ")
705
- }];
706
- }
707
- if (isPlainObject(value)) return Object.entries(value).flatMap(([key, child]) => collectLeafEntries(child, [...path, key]));
708
- return [];
709
- }
710
- function capLength(message) {
711
- if (message.length <= MAX_EXTRACTED_MESSAGE_LEN) return message;
712
- return message.slice(0, MAX_EXTRACTED_MESSAGE_LEN - ELLIPSIS.length) + ELLIPSIS;
713
- }
714
- function defaultMessageForStatus(status) {
715
- return STATUS_CLASSIFICATIONS[status]?.message ?? `Metabase returned ${status}.`;
716
- }
717
-
718
- //#endregion
719
- //#region src/core/http/network-error.ts
720
- const NETWORK_HINTS = {
721
- ECONNREFUSED: (t) => `Connection refused by ${t.host} — is Metabase running and is the port correct?`,
722
- ENOTFOUND: (t) => `Host not found: ${t.hostname} — check the URL.`,
723
- EAI_AGAIN: (t) => `Could not resolve ${t.hostname} — check your network connection and the URL.`,
724
- ECONNRESET: (t) => `Connection to ${t.host} was reset — the server may have closed it, or http/https may be mismatched.`,
725
- ETIMEDOUT: (t) => `Connection to ${t.host} timed out — check the host, port, and your network.`
726
- };
727
- const TLS_ERROR_CODES = new Set([
728
- "EPROTO",
729
- "DEPTH_ZERO_SELF_SIGNED_CERT",
730
- "SELF_SIGNED_CERT_IN_CHAIN",
731
- "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
732
- "CERT_HAS_EXPIRED",
733
- "ERR_TLS_CERT_ALTNAME_INVALID"
734
- ]);
735
- function buildNetworkError(error, method, url) {
736
- const fallback = errorMessage(error);
737
- const code = causeCode(error);
738
- const target = networkTarget(url);
739
- return new NetworkError(networkMessage(code, target, fallback), {
740
- method,
741
- url,
742
- cause: code ?? fallback
743
- });
744
- }
745
- function networkMessage(code, target, fallback) {
746
- if (code === null) return `Could not reach Metabase: ${fallback}`;
747
- if (TLS_ERROR_CODES.has(code)) return `Could not reach Metabase: TLS error contacting ${target.host} (${code}) — the certificate could not be verified, or https:// was used against a plain-HTTP server.`;
748
- const hint = NETWORK_HINTS[code];
749
- if (hint === void 0) return `Could not reach Metabase: ${fallback} (${code})`;
750
- return `Could not reach Metabase: ${hint(target)}`;
751
- }
752
- function causeCode(error) {
753
- const cause = error instanceof Error ? error.cause : void 0;
754
- if (cause instanceof Error && "code" in cause && typeof cause.code === "string") return cause.code;
755
- return null;
756
- }
757
- function networkTarget(url) {
758
- const parsed = new URL(url);
759
- return {
760
- host: parsed.host,
761
- hostname: parsed.hostname
762
- };
763
- }
764
-
765
- //#endregion
766
- //#region src/core/http/retry.ts
767
- const DEFAULT_MAX_RETRIES = 3;
768
- const BASE_DELAY_MS = 250;
769
- const MAX_DELAY_MS = 8e3;
770
- const MS_PER_SECOND = 1e3;
771
- function backoffDelay({ attempt, retryAfterHeader }) {
772
- const fromHeader = parseRetryAfter(retryAfterHeader);
773
- if (fromHeader !== null) return fromHeader;
774
- return Math.min(MAX_DELAY_MS, BASE_DELAY_MS * 2 ** attempt);
775
- }
776
- function parseRetryAfter(header) {
777
- if (!header) return null;
778
- const numeric = Number(header);
779
- if (Number.isFinite(numeric) && numeric >= 0) return Math.round(numeric * MS_PER_SECOND);
780
- const dateMs = Date.parse(header);
781
- if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
782
- return null;
783
- }
784
- function sleep(ms, signal) {
785
- return setTimeout(ms, void 0, { signal });
786
- }
787
- async function runWithRetries(attempt, signal) {
788
- let attemptIndex = 0;
789
- while (true) {
790
- const outcome = await attempt(attemptIndex);
791
- if (outcome.kind === "success") return outcome.response;
792
- await sleep(outcome.delayMs, signal);
793
- attemptIndex += 1;
794
- }
795
- }
796
-
797
- //#endregion
798
- //#region src/core/http/client.ts
799
- const UNAUTHORIZED_STATUS = 401;
800
- const DEFAULT_TIMEOUT_MS = 3e4;
801
- const OCTET_STREAM_CONTENT_TYPE = "application/octet-stream";
802
- const TEXT_CONTENT_TYPE_PREFIX = "text/";
803
- const ERROR_BODY_BYTE_CAP = 64 * 1024;
804
- const USER_AGENT = `metabase-cli/${package_default.version}`;
805
- const IDEMPOTENT_METHODS = new Set([
806
- "GET",
807
- "HEAD",
808
- "OPTIONS"
809
- ]);
810
- const NO_SERVER_TAG = async () => null;
811
- function createClient(config, overrides = {}) {
812
- const fetchImpl = overrides.fetchImpl ?? globalThis.fetch.bind(globalThis);
813
- const getServerTag = overrides.getServerTag ?? NO_SERVER_TAG;
814
- const refreshCredential = overrides.refreshCredential;
815
- let credential = config.credential;
816
- const knownSecrets = new Set(credentialSecrets(credential));
817
- const redactionContext = { knownSecrets };
818
- let refreshInFlight = null;
819
- function tryRefreshCredential() {
820
- const refresh = refreshCredential;
821
- if (credential.kind !== "oauth" || refresh === void 0) return Promise.resolve(false);
822
- refreshInFlight ??= refreshOnce(refresh).finally(() => {
823
- refreshInFlight = null;
824
- });
825
- return refreshInFlight;
826
- }
827
- async function refreshOnce(refresh) {
828
- const next = await refresh();
829
- if (next === null) return false;
830
- credential = next;
831
- for (const secret of credentialSecrets(next)) knownSecrets.add(secret);
832
- return true;
833
- }
834
- async function attemptOnce(prepared, attempt) {
835
- const hasRetriesLeft = attempt < prepared.retries;
836
- const timeoutSignal = AbortSignal.timeout(prepared.timeoutMs);
837
- const { combined, processSignal } = combineAborts(timeoutSignal, prepared.callerSignal);
838
- let response;
839
- try {
840
- response = await fetchImpl(prepared.url, {
841
- method: prepared.method,
842
- headers: prepared.headers,
843
- body: prepared.body,
844
- signal: combined
845
- });
846
- } catch (error) {
847
- throwIfAborted(prepared.callerSignal, processSignal);
848
- if (hasRetriesLeft) return {
849
- kind: "retry",
850
- delayMs: backoffDelay({ attempt })
851
- };
852
- if (timeoutSignal.aborted) throw new TimeoutError(`Request timed out after ${prepared.timeoutMs}ms`, {
853
- kind: "http",
854
- method: prepared.method,
855
- url: prepared.url,
856
- timeoutMs: prepared.timeoutMs
857
- });
858
- throw buildNetworkError(error, prepared.method, prepared.url);
859
- }
860
- const canRetryStatus = hasRetriesLeft && prepared.idempotent;
861
- if (!response.ok && isRetryableStatus(response.status) && canRetryStatus) {
862
- const retryAfter = response.headers.get("Retry-After");
863
- response.body?.cancel().catch(() => void 0);
864
- return {
865
- kind: "retry",
866
- delayMs: backoffDelay({
867
- attempt,
868
- retryAfterHeader: retryAfter
869
- })
870
- };
871
- }
872
- if (!response.ok) {
873
- const rawBody = await readBodyForError(response);
874
- const serverTag = await getServerTag();
875
- throw new HttpError({
876
- status: response.status,
877
- statusText: response.statusText,
878
- method: prepared.method,
879
- url: prepared.url,
880
- responseHeaders: response.headers,
881
- rawBody,
882
- serverTag,
883
- redactionContext
884
- });
885
- }
886
- assertContentType(response, prepared);
887
- return {
888
- kind: "success",
889
- response
890
- };
891
- }
892
- async function executeRaw(prepared) {
893
- return runWithRetries((attempt) => attemptOnce(prepared, attempt), prepared.callerSignal);
894
- }
895
- async function executeWithAuthRefresh(path, opts) {
896
- const prepared = prepare(path, opts);
897
- try {
898
- return {
899
- response: await executeRaw(prepared),
900
- prepared
901
- };
902
- } catch (error) {
903
- if (error instanceof HttpError && error.status === UNAUTHORIZED_STATUS) {
904
- if (await tryRefreshCredential()) {
905
- const retried = prepare(path, opts);
906
- return {
907
- response: await executeRaw(retried),
908
- prepared: retried
909
- };
910
- }
911
- }
912
- throw error;
913
- }
914
- }
915
- function prepare(path, opts = {}) {
916
- const method = opts.method ?? "GET";
917
- const expectContentType = opts.expectContentType ?? "json";
918
- const url = buildUrl(config.url, path, opts.query);
919
- const headers = new Headers();
920
- const auth = credentialAuthHeader(credential);
921
- headers.set(auth.name, auth.value);
922
- headers.set("accept", acceptHeader(expectContentType));
923
- headers.set("user-agent", USER_AGENT);
924
- let body = null;
925
- if (opts.body !== void 0 && opts.body !== null) if (typeof opts.body === "string" || opts.body instanceof URLSearchParams) body = opts.body;
926
- else if (opts.body instanceof FormData || opts.body instanceof ReadableStream) body = opts.body;
927
- else if (opts.body instanceof Uint8Array) {
928
- body = opts.body;
929
- headers.set("content-type", OCTET_STREAM_CONTENT_TYPE);
930
- } else {
931
- body = JSON.stringify(opts.body);
932
- headers.set("content-type", JSON_CONTENT_TYPE);
933
- }
934
- return {
935
- url,
936
- method,
937
- headers,
938
- body,
939
- expectContentType,
940
- retries: opts.retries ?? DEFAULT_MAX_RETRIES,
941
- idempotent: opts.idempotent ?? IDEMPOTENT_METHODS.has(method),
942
- timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
943
- callerSignal: opts.signal
944
- };
945
- }
946
- return {
947
- async requestRaw(path, opts) {
948
- return (await executeWithAuthRefresh(path, opts ?? {})).response;
949
- },
950
- async requestParsed(schema, path, opts) {
951
- const { response, prepared } = await executeWithAuthRefresh(path, {
952
- ...opts,
953
- expectContentType: "json"
954
- });
955
- const text = await response.text();
956
- try {
957
- return parseJson(text, schema, { source: prepared.url });
958
- } catch (error) {
959
- if (error instanceof ValidationError) throw new ResponseShapeError({
960
- method: prepared.method,
961
- url: prepared.url,
962
- status: response.status,
963
- zodIssues: error.developerDetail.zodIssues,
964
- serverTag: await getServerTag()
965
- });
966
- throw error;
967
- }
968
- },
969
- async requestStream(path, opts) {
970
- const { response, prepared } = await executeWithAuthRefresh(path, {
971
- ...opts,
972
- expectContentType: opts?.expectContentType ?? "binary"
973
- });
974
- if (!response.body) throw new NetworkError("Response had no body to stream", {
975
- method: prepared.method,
976
- url: prepared.url,
977
- cause: "missing body"
978
- });
979
- return response.body;
980
- }
981
- };
982
- }
983
- function buildUrl(baseUrl, path, query) {
984
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
985
- const target = new URL(baseUrl + normalizedPath);
986
- if (query) for (const [key, value] of Object.entries(query)) {
987
- if (value === void 0) continue;
988
- if (Array.isArray(value)) for (const entry of value) target.searchParams.append(key, String(entry));
989
- else target.searchParams.append(key, String(value));
990
- }
991
- return target.toString();
992
- }
993
- function acceptHeader(expected) {
994
- if (expected === "json") return JSON_CONTENT_TYPE;
995
- if (expected === "text") return "text/*";
996
- return "*/*";
997
- }
998
- function assertContentType(response, prepared) {
999
- if (prepared.expectContentType === "binary") return;
1000
- const contentType = response.headers.get("content-type");
1001
- if (contentType === null) throwContentTypeMismatch(response, prepared, prepared.expectContentType);
1002
- if (prepared.expectContentType === "json" && !contentType.includes(JSON_CONTENT_TYPE)) throwContentTypeMismatch(response, prepared, "json");
1003
- if (prepared.expectContentType === "text" && !contentType.startsWith(TEXT_CONTENT_TYPE_PREFIX)) throwContentTypeMismatch(response, prepared, "text");
1004
- }
1005
- function throwContentTypeMismatch(response, prepared, expected) {
1006
- const actual = response.headers.get("content-type") ?? "no content-type";
1007
- throw new HttpError({
1008
- status: response.status,
1009
- statusText: response.statusText,
1010
- method: prepared.method,
1011
- url: prepared.url,
1012
- responseHeaders: response.headers,
1013
- rawBody: null,
1014
- overrideUserMessage: `Expected ${expected} response but got ${actual}`
1015
- });
1016
- }
1017
- async function readBodyForError(response) {
1018
- try {
1019
- const buffer = Buffer.from(await response.arrayBuffer());
1020
- return buffer.subarray(0, ERROR_BODY_BYTE_CAP).toString("utf8");
1021
- } catch (error) {
1022
- return `[body read failed: ${errorMessage(error)}]`;
1023
- }
1024
- }
1025
-
1026
- //#endregion
1027
- //#region src/core/version/probe.ts
1028
- const PROBE_PATH = "/api/session/properties";
1029
- const PROBE_TIMEOUT_MS = 1e4;
1030
- async function probeServer(client, opts = {}) {
1031
- const properties = await client.requestParsed(SessionProperties, PROBE_PATH, {
1032
- timeoutMs: PROBE_TIMEOUT_MS,
1033
- retries: opts.retries ?? 0
1034
- });
1035
- const version = tryParseTag(properties.version.tag);
1036
- return {
1037
- version,
1038
- tokenFeatures: properties["token-features"] ?? null
1039
- };
1040
- }
1041
-
1042
- //#endregion
1043
- //#region src/core/url.ts
1044
- function normalizeUrl(input) {
1045
- const trimmed = input.trim().replace(/\/+$/, "");
1046
- if (!/^https?:\/\//i.test(trimmed)) throw new ConfigError("URL must start with http:// or https://");
1047
- return trimmed;
1048
- }
1049
- function displayUrl(input) {
1050
- const parsed = new URL(input);
1051
- const path = parsed.pathname.replace(/\/+$/, "");
1052
- return `${parsed.origin}${path}`;
1053
- }
1054
- const LOOPBACK_HOSTS = new Set([
1055
- "localhost",
1056
- "127.0.0.1",
1057
- "::1",
1058
- "[::1]"
1059
- ]);
1060
- function isLoopbackHost(hostname) {
1061
- return LOOPBACK_HOSTS.has(hostname.toLowerCase());
1062
- }
1063
- function assertEndpointOrigin(endpoint, baseUrl, label) {
1064
- let parsed;
1065
- try {
1066
- parsed = new URL(endpoint);
1067
- } catch {
1068
- throw new ConfigError(`OAuth ${label} is not a valid URL: ${endpoint}`);
1069
- }
1070
- const base = new URL(baseUrl);
1071
- if (parsed.protocol !== "https:" && !isLoopbackHost(parsed.hostname)) throw new ConfigError(`OAuth ${label} must use https: ${endpoint}`);
1072
- if (parsed.origin !== base.origin) throw new ConfigError(`OAuth ${label} origin (${parsed.origin}) does not match the Metabase URL (${base.origin})`);
1073
- }
1074
-
1075
- //#endregion
1076
- //#region src/core/http/oauth.ts
1077
- const DISCOVERY_PATH = "/.well-known/oauth-authorization-server";
1078
- const FORM_CONTENT_TYPE = "application/x-www-form-urlencoded";
1079
- const OAUTH_TIMEOUT_MS = 3e4;
1080
- async function oauthFetch(request) {
1081
- const timeoutSignal = AbortSignal.timeout(OAUTH_TIMEOUT_MS);
1082
- try {
1083
- return await fetch(request.url, {
1084
- method: request.method,
1085
- headers: {
1086
- ...request.headers,
1087
- "user-agent": USER_AGENT
1088
- },
1089
- ...request.body !== void 0 ? { body: request.body } : {},
1090
- signal: timeoutSignal
1091
- });
1092
- } catch (error) {
1093
- if (timeoutSignal.aborted) throw new TimeoutError(`OAuth request timed out after ${OAUTH_TIMEOUT_MS}ms`, {
1094
- kind: "http",
1095
- method: request.method,
1096
- url: request.url,
1097
- timeoutMs: OAUTH_TIMEOUT_MS
1098
- });
1099
- throw buildNetworkError(error, request.method, request.url);
1100
- }
1101
- }
1102
- const OAUTH_SCOPE = "mb:full";
1103
- const OAuthServerMetadata = z.object({
1104
- issuer: z.string(),
1105
- authorization_endpoint: z.string(),
1106
- token_endpoint: z.string(),
1107
- registration_endpoint: z.string().optional(),
1108
- revocation_endpoint: z.string().optional(),
1109
- scopes_supported: z.array(z.string()).optional()
1110
- }).loose();
1111
- const RegisteredClient = z.object({ client_id: z.string() }).loose();
1112
- const OAuthTokens = z.object({
1113
- access_token: z.string(),
1114
- token_type: z.string(),
1115
- expires_in: z.number().int().optional(),
1116
- refresh_token: z.string().optional()
1117
- }).loose();
1118
- const OAuthErrorBody = z.object({
1119
- error: z.string(),
1120
- error_description: z.string().optional()
1121
- }).loose();
1122
- async function readJson(response, schema, source) {
1123
- let raw;
1124
- try {
1125
- raw = await response.json();
1126
- } catch (error) {
1127
- throw new ConfigError(`${source}: invalid JSON response (${errorMessage(error)})`);
1128
- }
1129
- const parsed = schema.safeParse(raw);
1130
- if (!parsed.success) throw new ConfigError(`${source}: unexpected response shape`);
1131
- return parsed.data;
1132
- }
1133
- async function failure(response, source, method, url) {
1134
- const rawBody = await response.text().catch(() => "");
1135
- if (isRetryableStatus(response.status)) return new HttpError({
1136
- status: response.status,
1137
- statusText: response.statusText,
1138
- method,
1139
- url,
1140
- responseHeaders: response.headers,
1141
- rawBody
1142
- });
1143
- const parsed = parseJsonResult(rawBody, OAuthErrorBody);
1144
- if (parsed.ok) {
1145
- const detail = parsed.value.error_description ?? parsed.value.error;
1146
- return new ConfigError(`${source} failed (${response.status}): ${detail}`);
1147
- }
1148
- return new ConfigError(`${source} failed (${response.status})`);
1149
- }
1150
- async function postForm(url, params, schema, source) {
1151
- const response = await oauthFetch({
1152
- url,
1153
- method: "POST",
1154
- headers: {
1155
- "content-type": FORM_CONTENT_TYPE,
1156
- accept: JSON_CONTENT_TYPE
1157
- },
1158
- body: new URLSearchParams(params)
1159
- });
1160
- if (!response.ok) throw await failure(response, source, "POST", url);
1161
- return readJson(response, schema, source);
1162
- }
1163
- const OAUTH_UNSUPPORTED_MESSAGE = "this Metabase does not support OAuth login (requires Metabase v63 or newer)";
1164
- async function tryDiscoverMetadata(baseUrl) {
1165
- const url = `${baseUrl}${DISCOVERY_PATH}`;
1166
- const response = await oauthFetch({
1167
- url,
1168
- method: "GET",
1169
- headers: { accept: JSON_CONTENT_TYPE }
1170
- });
1171
- const contentType = response.headers.get("content-type") ?? "";
1172
- if (!response.ok || !contentType.includes("json")) {
1173
- await response.body?.cancel().catch(() => void 0);
1174
- return null;
1175
- }
1176
- const metadata = await readJson(response, OAuthServerMetadata, "OAuth discovery");
1177
- const scopes = metadata.scopes_supported;
1178
- if (scopes !== void 0 && !scopes.includes(OAUTH_SCOPE)) return null;
1179
- assertEndpointOrigin(metadata.issuer, baseUrl, "issuer");
1180
- assertEndpointOrigin(metadata.authorization_endpoint, baseUrl, "authorization endpoint");
1181
- assertEndpointOrigin(metadata.token_endpoint, baseUrl, "token endpoint");
1182
- if (metadata.registration_endpoint !== void 0) assertEndpointOrigin(metadata.registration_endpoint, baseUrl, "registration endpoint");
1183
- if (metadata.revocation_endpoint !== void 0) assertEndpointOrigin(metadata.revocation_endpoint, baseUrl, "revocation endpoint");
1184
- return metadata;
1185
- }
1186
- async function discoverMetadata(baseUrl) {
1187
- const metadata = await tryDiscoverMetadata(baseUrl);
1188
- if (metadata === null) throw new ConfigError(OAUTH_UNSUPPORTED_MESSAGE);
1189
- return metadata;
1190
- }
1191
- async function registerClient(input) {
1192
- const response = await oauthFetch({
1193
- url: input.registrationEndpoint,
1194
- method: "POST",
1195
- headers: {
1196
- "content-type": JSON_CONTENT_TYPE,
1197
- accept: JSON_CONTENT_TYPE
1198
- },
1199
- body: JSON.stringify({
1200
- application_type: "native",
1201
- client_name: input.clientName,
1202
- redirect_uris: [input.redirectUri],
1203
- grant_types: ["authorization_code", "refresh_token"],
1204
- response_types: ["code"],
1205
- token_endpoint_auth_method: "none",
1206
- scope: OAUTH_SCOPE
1207
- })
1208
- });
1209
- if (!response.ok) throw await failure(response, "OAuth client registration", "POST", input.registrationEndpoint);
1210
- return readJson(response, RegisteredClient, "OAuth client registration");
1211
- }
1212
- function exchangeCode(input) {
1213
- return postForm(input.tokenEndpoint, {
1214
- grant_type: "authorization_code",
1215
- code: input.code,
1216
- redirect_uri: input.redirectUri,
1217
- client_id: input.clientId,
1218
- code_verifier: input.codeVerifier
1219
- }, OAuthTokens, "OAuth token exchange");
1220
- }
1221
- function refreshTokens(input) {
1222
- return postForm(input.tokenEndpoint, {
1223
- grant_type: "refresh_token",
1224
- refresh_token: input.refreshToken,
1225
- client_id: input.clientId
1226
- }, OAuthTokens, "OAuth token refresh");
1227
- }
1228
- async function revokeToken(input) {
1229
- const response = await oauthFetch({
1230
- url: input.revocationEndpoint,
1231
- method: "POST",
1232
- headers: { "content-type": FORM_CONTENT_TYPE },
1233
- body: new URLSearchParams({
1234
- token: input.token,
1235
- client_id: input.clientId
1236
- })
1237
- });
1238
- if (!response.ok) throw await failure(response, "OAuth token revocation", "POST", input.revocationEndpoint);
1239
- await response.body?.cancel().catch(() => void 0);
1240
- }
1241
-
1242
- //#endregion
1243
- //#region src/core/auth/oauth-session.ts
1244
- async function refreshOAuthCredential(baseUrl, credential, nowMs) {
1245
- const metadata = await discoverMetadata(baseUrl);
1246
- const tokens = await refreshTokens({
1247
- tokenEndpoint: metadata.token_endpoint,
1248
- refreshToken: credential.refreshToken,
1249
- clientId: credential.clientId
1250
- });
1251
- return oauthCredentialFromTokens(tokens, tokens.refresh_token ?? credential.refreshToken, credential.clientId, nowMs);
1252
- }
1253
- async function revokeOAuthCredential(baseUrl, credential) {
1254
- const metadata = await discoverMetadata(baseUrl);
1255
- const revocationEndpoint = metadata.revocation_endpoint;
1256
- if (revocationEndpoint === void 0) return false;
1257
- await revokeToken({
1258
- revocationEndpoint,
1259
- token: credential.refreshToken,
1260
- clientId: credential.clientId
1261
- });
1262
- await revokeToken({
1263
- revocationEndpoint,
1264
- token: credential.accessToken,
1265
- clientId: credential.clientId
1266
- });
1267
- return true;
1268
- }
1269
-
1270
- //#endregion
1271
- //#region src/core/config.ts
1272
- function isPreflightSkipped() {
1273
- return readEnv(ENV_SKIP_PREFLIGHT) === "1";
1274
- }
1275
- function resolveProfileName(profileFlag) {
1276
- return explicitProfileName(profileFlag) ?? DEFAULT_PROFILE;
1277
- }
1278
- function explicitProfileName(profileFlag) {
1279
- return profileFlag || readEnv(ENV_PROFILE) || null;
1280
- }
1281
- function readEnvCredentials() {
1282
- return {
1283
- url: readEnv(ENV_URL) ?? null,
1284
- apiKey: readEnv(ENV_API_KEY) ?? null
1285
- };
1286
- }
1287
- async function resolveConfig(flags) {
1288
- const profile = resolveProfileName(flags.profile);
1289
- const env = readEnvCredentials();
1290
- const hasUrl = Boolean(flags.url ?? env.url);
1291
- const hasKey = Boolean(flags.apiKey ?? env.apiKey);
1292
- const stored = hasUrl && hasKey ? null : await readProfileCredential(profile);
1293
- const url = resolveUrl(flags.url, env.url, stored?.url);
1294
- const credential = resolveCredential(flags.apiKey, env.apiKey, stored?.credential);
1295
- if (url === null || credential === null) {
1296
- const hint = await failureHintForProfile(profile);
1297
- throw new ConfigError(`Not authenticated for profile "${profile}". Run \`mb auth login\`, set ${ENV_URL}/${ENV_API_KEY}, or pass --url/--api-key.${hint}`);
1298
- }
1299
- const normalizedUrl = normalizeUrl(url.value);
1300
- assertOAuthUrlMatchesIssuer(credential.credential, stored?.url, normalizedUrl, profile);
1301
- const fresh = await ensureFreshCredential(profile, credential.credential, stored?.url);
1302
- return {
1303
- url: normalizedUrl,
1304
- credential: fresh,
1305
- profile,
1306
- source: url.source === credential.source ? url.source : "mixed"
1307
- };
1308
- }
1309
- function assertOAuthUrlMatchesIssuer(credential, issuerUrl, requestUrl, profile) {
1310
- if (credential.kind !== "oauth" || issuerUrl === void 0) return;
1311
- const issuer = normalizeUrl(issuerUrl);
1312
- if (issuer === requestUrl) return;
1313
- throw new ConfigError(`profile "${profile}" is a browser-login (OAuth) profile bound to ${issuer}, but the request URL is ${requestUrl}. Drop --url/${ENV_URL} to use the profile's own URL, or run \`mb auth login --url ${requestUrl}\` to authenticate there.`);
1314
- }
1315
- async function ensureFreshCredential(profile, credential, issuerUrl) {
1316
- if (credential.kind !== "oauth" || issuerUrl === void 0) return credential;
1317
- if (!isOAuthExpired(credential, Date.now())) return credential;
1318
- let refreshed;
1319
- try {
1320
- refreshed = await refreshOAuthCredential(issuerUrl, credential, Date.now());
1321
- } catch {
1322
- return credential;
1323
- }
1324
- await persistRefreshed(profile, issuerUrl, refreshed);
1325
- return refreshed;
1326
- }
1327
- async function refreshAndPersist(profile, issuerUrl, credential) {
1328
- const refreshed = await refreshOAuthCredential(issuerUrl, credential, Date.now());
1329
- await persistRefreshed(profile, issuerUrl, refreshed);
1330
- return refreshed;
1331
- }
1332
- async function persistRefreshed(profile, issuerUrl, refreshed) {
1333
- await writeOAuthProfile(issuerUrl, refreshed, profile);
1334
- }
1335
- function createCredentialRefresher(profile) {
1336
- return async () => {
1337
- const stored = await readProfileCredential(profile);
1338
- if (stored === null || stored.credential.kind !== "oauth") return null;
1339
- try {
1340
- return await refreshAndPersist(profile, stored.url, stored.credential);
1341
- } catch (error) {
1342
- if (error instanceof ConfigError) throw new ConfigError(`${error.message} — run \`mb auth login --profile ${profile}\` to log in again`);
1343
- throw error;
1344
- }
1345
- };
1346
- }
1347
- async function failureHintForProfile(profile) {
1348
- const record = await readProfileRecord(profile);
1349
- if (record === null || record.lastFailure === null) return "";
1350
- if (record.lastProbe !== null && record.lastProbe.at >= record.lastFailure.at) return "";
1351
- return ` profile "${profile}" last verify failed: ${record.lastFailure.reason}. Run \`mb auth login --profile ${profile}\` to update the token.`;
1352
- }
1353
- function resolveUrl(flag, env, stored) {
1354
- if (flag) return {
1355
- value: flag,
1356
- source: "flag"
1357
- };
1358
- if (env) return {
1359
- value: env,
1360
- source: "env"
1361
- };
1362
- if (stored) return {
1363
- value: stored,
1364
- source: "stored"
1365
- };
1366
- return null;
1367
- }
1368
- function resolveCredential(flagKey, envKey, stored) {
1369
- if (flagKey) return {
1370
- credential: {
1371
- kind: "apiKey",
1372
- apiKey: flagKey
1373
- },
1374
- source: "flag"
1375
- };
1376
- if (envKey) return {
1377
- credential: {
1378
- kind: "apiKey",
1379
- apiKey: envKey
1380
- },
1381
- source: "env"
1382
- };
1383
- if (stored) return {
1384
- credential: stored,
1385
- source: "stored"
1386
- };
1387
- return null;
1388
- }
1389
-
1390
- //#endregion
1391
- //#region src/core/version/capabilities.ts
1392
- function mergeCapabilities(overrides) {
1393
- if (overrides === void 0) return BASELINE_CAPABILITIES;
1394
- return {
1395
- minVersion: overrides.minVersion ?? BASELINE_CAPABILITIES.minVersion,
1396
- ...overrides.tokenFeature === void 0 ? {} : { tokenFeature: overrides.tokenFeature }
1397
- };
1398
- }
1399
- function checkCapabilities(info, required) {
1400
- if (info.version === null) return {
1401
- reason: "unknown-version",
1402
- detail: "Could not detect Metabase server version. Proceeding without preflight check; failures may produce confusing errors."
1403
- };
1404
- if (info.version.major < required.minVersion) return {
1405
- reason: "version-too-old",
1406
- detail: `This command requires Metabase v${required.minVersion}+ (this server is ${info.version.tag}). Upgrade Metabase or pin mb-cli to an older release.`
1407
- };
1408
- if (required.tokenFeature !== void 0) {
1409
- const enabled = info.tokenFeatures?.[required.tokenFeature] === true;
1410
- if (!enabled) return {
1411
- reason: "missing-token-feature",
1412
- detail: `This command requires the '${required.tokenFeature}' premium feature (not enabled on this server).`
1413
- };
1414
- }
1415
- return null;
1416
- }
1417
-
1418
- //#endregion
1419
- //#region src/core/version/preflight-error.ts
1420
- var CapabilityError = class extends MetabaseError {
1421
- category = "capability";
1422
- isRetryable = false;
1423
- exitCode = 2;
1424
- developerDetail;
1425
- constructor(failure$1) {
1426
- super(failure$1.detail);
1427
- this.name = "CapabilityError";
1428
- this.developerDetail = failure$1;
1429
- }
1430
- };
1431
-
1432
- //#endregion
1433
- //#region src/output/format.ts
1434
- function resolveFormat({ json, format, isTty }) {
1435
- const explicit = format !== void 0 && format !== "auto" ? format : null;
1436
- if (explicit !== null && explicit !== "json" && explicit !== "text") throw new ConfigError(`invalid --format value: "${explicit}" (expected: auto, json, text)`);
1437
- if (json && explicit !== null && explicit !== "json") throw new ConfigError(`--json conflicts with --format ${explicit}`);
1438
- if (json) return "json";
1439
- if (explicit !== null) return explicit;
1440
- return isTty ? "text" : "json";
1441
- }
1442
-
1443
- //#endregion
1444
- //#region src/runtime/csv.ts
1445
- function parseCsv(raw) {
1446
- return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
1447
- }
1448
- function parseEnumCsv(raw, schema, flagName) {
1449
- if (raw === void 0 || raw === "") return void 0;
1450
- const parts = parseCsv(raw);
1451
- if (parts.length === 0) return void 0;
1452
- const accepted = [];
1453
- const rejected = [];
1454
- for (const part of parts) {
1455
- const result = schema.safeParse(part);
1456
- if (result.success) accepted.push(result.data);
1457
- else rejected.push(part);
1458
- }
1459
- if (rejected.length > 0) {
1460
- const allowed = Object.values(schema.enum).join(", ");
1461
- throw new ConfigError(`invalid ${flagName} value: ${rejected.join(", ")} (expected one of: ${allowed})`);
1462
- }
1463
- return accepted;
1464
- }
1465
- function parseEnum(raw, schema, flagName) {
1466
- if (raw === void 0 || raw === "") return void 0;
1467
- const result = schema.safeParse(raw);
1468
- if (!result.success) {
1469
- const allowed = Object.values(schema.enum).join(", ");
1470
- throw new ConfigError(`invalid ${flagName} value: "${raw}" (expected one of: ${allowed})`);
1471
- }
1472
- return result.data;
1473
- }
1474
-
1475
- //#endregion
1476
- //#region src/commands/parse-integer.ts
1477
- const INTEGER_PATTERN = /^-?\d+$/;
1478
- function parseInteger(value, options) {
1479
- const trimmed = value.trim();
1480
- if (!INTEGER_PATTERN.test(trimmed)) throw new ConfigError(`invalid ${options.name}: "${value}" (expected integer)`);
1481
- const parsed = Number.parseInt(trimmed, 10);
1482
- if (parsed < options.min) throw new ConfigError(`invalid ${options.name}: ${parsed} (must be ≥ ${options.min})`);
1483
- return parsed;
1484
- }
1485
-
1486
- //#endregion
1487
- //#region src/commands/context.ts
1488
- function resolveCommonFlags(args, options = {}) {
1489
- const isTty = options.isTty ?? Boolean(process.stdout.isTTY);
1490
- const fields = parseFields(args.fields);
1491
- const full = args.full === true;
1492
- if (full && fields !== void 0) throw new ConfigError("--full conflicts with --fields (use one or neither)");
1493
- return {
1494
- format: resolveFormat({
1495
- json: args.json,
1496
- format: args.format,
1497
- isTty
1498
- }),
1499
- full,
1500
- fields,
1501
- maxBytes: parseMaxBytes(args.maxBytes),
1502
- url: args.url,
1503
- apiKey: args.apiKey,
1504
- profile: args.profile,
1505
- skipPreflight: args.skipPreflight === true
1506
- };
1507
- }
1508
- function parseFields(value) {
1509
- if (value === void 0 || value === "") return void 0;
1510
- const parts = parseCsv(value);
1511
- return parts.length > 0 ? parts : void 0;
1512
- }
1513
- function parseMaxBytes(value) {
1514
- return parseInteger(value ?? String(DEFAULT_MAX_BYTES), {
1515
- name: "--max-bytes",
1516
- min: 0
1517
- });
1518
- }
1519
-
1520
- //#endregion
1521
- //#region src/commands/known-flags.ts
1522
- const ARGUMENT_SEPARATOR = "--";
1523
- const NEGATION_PREFIX = "no-";
1524
- const BUILTIN_FLAGS = [
1525
- "help",
1526
- "h",
1527
- "version",
1528
- "v"
1529
- ];
1530
- function assertKnownFlags(rawArgs, argsDef) {
1531
- const allowed = allowedFlagKeys(argsDef);
1532
- let index = 0;
1533
- while (index < rawArgs.length) {
1534
- const token = rawArgs[index];
1535
- if (token === void 0 || token === ARGUMENT_SEPARATOR) return;
1536
- if (!isFlagToken(token)) {
1537
- index += 1;
1538
- continue;
1539
- }
1540
- const matched = flagCandidates(token).some((candidate) => allowed.has(candidate));
1541
- if (!matched) throw new ConfigError(`unknown flag: ${displayFlag(token)}`);
1542
- index += flagConsumesValue(token, argsDef) ? 2 : 1;
1543
- }
1544
- }
1545
- function allowedFlagKeys(argsDef) {
1546
- const keys = new Set(BUILTIN_FLAGS.map(normalizeFlag));
1547
- for (const [name, def] of Object.entries(argsDef)) {
1548
- keys.add(normalizeFlag(name));
1549
- if ("alias" in def) for (const alias of toAliasArray(def.alias)) keys.add(normalizeFlag(alias));
1550
- }
1551
- return keys;
1552
- }
1553
- function isFlagToken(token) {
1554
- return token.startsWith("-") && token !== "-";
1555
- }
1556
- function displayFlag(token) {
1557
- const equals = token.indexOf("=");
1558
- return equals === -1 ? token : token.slice(0, equals);
1559
- }
1560
- function flagCandidates(token) {
1561
- const name = displayFlag(token).replace(/^-+/, "");
1562
- const candidates = [normalizeFlag(name)];
1563
- if (name.startsWith(NEGATION_PREFIX)) candidates.push(normalizeFlag(name.slice(NEGATION_PREFIX.length)));
1564
- return candidates;
1565
- }
1566
-
1567
- //#endregion
1568
- //#region src/commands/runtime.ts
1569
- function defineMetabaseCommand(def) {
1570
- const required = def.capabilities === null ? null : mergeCapabilities(def.capabilities);
1571
- const cmd = defineCommand({
1572
- meta: def.meta,
1573
- args: def.args,
1574
- async run({ args, rawArgs }) {
1575
- let reportFormat;
1576
- try {
1577
- const ctx = resolveCommonFlags(pickCommonArgs(args));
1578
- reportFormat = ctx.format;
1579
- assertKnownFlags(rawArgs, def.args);
1580
- let cachedConfig = null;
1581
- let cachedClient = null;
1582
- let cachedServerInfo = null;
1583
- const getResolvedConfig = async () => {
1584
- if (cachedConfig === null) cachedConfig = await resolveConfig(buildConfigFlags(ctx));
1585
- return cachedConfig;
1586
- };
1587
- const getServerInfo = () => {
1588
- if (cachedServerInfo === null) cachedServerInfo = loadServerInfo(getResolvedConfig);
1589
- return cachedServerInfo;
1590
- };
1591
- const rawGetClient = async () => {
1592
- if (cachedClient === null) {
1593
- const resolved = await getResolvedConfig();
1594
- cachedClient = createClient({
1595
- url: resolved.url,
1596
- credential: resolved.credential
1597
- }, {
1598
- getServerTag: async () => (await getServerInfo())?.version?.tag ?? null,
1599
- refreshCredential: createCredentialRefresher(resolved.profile)
1600
- });
1601
- }
1602
- return cachedClient;
1603
- };
1604
- const enforcePreflight = createPreflightEnforcer(required, getServerInfo, ctx.skipPreflight);
1605
- const getClient = async () => {
1606
- const client = await rawGetClient();
1607
- await enforcePreflight();
1608
- return client;
1609
- };
1610
- try {
1611
- await def.run({
1612
- args,
1613
- ctx,
1614
- getClient,
1615
- getResolvedConfig,
1616
- getServerInfo
1617
- });
1618
- } finally {
1619
- emitPendingWarnings();
1620
- }
1621
- } catch (error) {
1622
- reportError(error, reportFormat);
1623
- }
1624
- }
1625
- });
1626
- setMetabaseAugment(cmd, {
1627
- examples: def.examples ?? [],
1628
- details: def.details ? def.details : null,
1629
- skills: def.skills ?? [],
1630
- inputSchema: def.inputSchema ?? null,
1631
- outputSchema: def.outputSchema ?? null,
1632
- capabilities: required
1633
- });
1634
- return cmd;
1635
- }
1636
- function emitPendingWarnings() {
1637
- for (const message of consumeLegacyEnvWarnings()) warn(message);
1638
- const legacy = consumeLegacyStorageWarning();
1639
- if (legacy !== null) warn(legacy);
1640
- const downgrade = consumeKeyringDowngradeWarning();
1641
- if (downgrade !== null) warn(downgrade);
1642
- }
1643
- async function loadServerInfo(getResolvedConfig) {
1644
- const resolved = await getResolvedConfig();
1645
- const record = await readProfileRecord(resolved.profile);
1646
- if (record === null || record.lastProbe === null) return null;
1647
- return {
1648
- version: record.lastProbe.version,
1649
- tokenFeatures: record.lastProbe.tokenFeatures
1650
- };
1651
- }
1652
- const NO_OP_ENFORCER = async () => {};
1653
- const NO_PROBE_DATA_WARNING = "Could not detect Metabase server version. Proceeding without preflight check; failures may produce confusing errors. Run `mb auth list` (or `mb auth login`) to populate the version cache.";
1654
- function createPreflightEnforcer(required, getServerInfo, skip) {
1655
- if (required === null || skip || isPreflightSkipped() || isBaseline(required)) return NO_OP_ENFORCER;
1656
- let done = false;
1657
- return async () => {
1658
- if (done) return;
1659
- done = true;
1660
- const info = await getServerInfo();
1661
- if (info === null) {
1662
- warn(NO_PROBE_DATA_WARNING);
1663
- return;
1664
- }
1665
- const failure$1 = checkCapabilities(info, required);
1666
- if (failure$1 === null || failure$1.reason === "unknown-version") return;
1667
- throw new CapabilityError(failure$1);
1668
- };
1669
- }
1670
- function isBaseline(caps) {
1671
- return caps.minVersion === BASELINE_CAPABILITIES.minVersion && caps.tokenFeature === void 0;
1672
- }
1673
- function pickCommonArgs(args) {
1674
- const out = {};
1675
- if (typeof args["format"] === "string") out.format = args["format"];
1676
- if (typeof args["json"] === "boolean") out.json = args["json"];
1677
- if (typeof args["full"] === "boolean") out.full = args["full"];
1678
- if (typeof args["fields"] === "string") out.fields = args["fields"];
1679
- if (typeof args["maxBytes"] === "string") out.maxBytes = args["maxBytes"];
1680
- if (typeof args["profile"] === "string") out.profile = args["profile"];
1681
- if (typeof args["url"] === "string") out.url = args["url"];
1682
- if (typeof args["apiKey"] === "string") out.apiKey = args["apiKey"];
1683
- if (typeof args["skipPreflight"] === "boolean") out.skipPreflight = args["skipPreflight"];
1684
- return out;
1685
- }
1686
- function buildConfigFlags(ctx) {
1687
- const flags = {};
1688
- if (ctx.profile !== void 0) flags.profile = ctx.profile;
1689
- if (ctx.url !== void 0) flags.url = ctx.url;
1690
- if (ctx.apiKey !== void 0) flags.apiKey = ctx.apiKey;
1691
- return flags;
1692
- }
1693
-
1694
- //#endregion
1695
- export { DEFAULT_PROFILE, HttpError, OAUTH_SCOPE, ParsedVersionSchema, ProbedUser, ProfileAuthMethod, ProfileLastFailure, TokenFeatures, USER_AGENT, clearProfile, combineAborts, consumeKeychainResidualWarning, consumeKeyringDowngradeWarning, createClient, createCredentialRefresher, defineMetabaseCommand, discoverMetadata, displayUrl, exchangeCode, explicitProfileName, keyringFallbackWarning, listProfileRecords, normalizeUrl, oauthCredentialFromTokens, parseCsv, parseEnum, parseEnumCsv, parseInteger, parseJson, parseJsonOrPlain, probeServer, profileAuthMethod, readEnvCredentials, readProfileCredential, readProfileRecord, registerClient, resolveProfileName, resolveRecordCredential, revokeOAuthCredential, throwIfAborted, tryDiscoverMetadata, writeOAuthProfile, writeProbeFailure, writeProbeResult, writeProfile };