@metabase/cli 0.3.0-alpha.extract-api-client.e9b2dd5 → 0.3.1-alpha.fix-transform-test-ee-path.a3ca6dd

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 (269) hide show
  1. package/dist/{add-collection-B3Ty8SzB.mjs → add-collection-BEg-1pt8.mjs} +6 -9
  2. package/dist/{alert-DT-ee7yf.mjs → alert-CBwtJ3lE.mjs} +7 -7
  3. package/dist/{alerts-Bf2RH_p_.mjs → alerts-Bn9ZhFYK.mjs} +7 -7
  4. package/dist/{append-DFzQRPMd.mjs → append-F7kfyk0p.mjs} +6 -5
  5. package/dist/{archive-ByvA49Kz.mjs → archive-2VqBgcyE.mjs} +5 -5
  6. package/dist/{archive-4tmm946K.mjs → archive-3_KVbxIk.mjs} +4 -4
  7. package/dist/{archive-Cd29QC0c.mjs → archive-7tZyaUWv.mjs} +4 -4
  8. package/dist/{archive-Dr9Xnx_Z.mjs → archive-Bonv-Hcf.mjs} +6 -6
  9. package/dist/{archive-C7w49Grr.mjs → archive-BzEvapLz.mjs} +6 -6
  10. package/dist/{archive-CwAdlv63.mjs → archive-CAwDiQWt2.mjs} +6 -6
  11. package/dist/{archive-lQqs13Uz.mjs → archive-CE-RKcle.mjs} +6 -6
  12. package/dist/{archive-B6eXiyER.mjs → archive-Da3-hnRM.mjs} +4 -4
  13. package/dist/{archive-gid9Y09v.mjs → archive-IBHOtOMk.mjs} +4 -4
  14. package/dist/{archive-BxNPHxOY.mjs → archive-TBo05bZZ.mjs} +6 -6
  15. package/dist/{archive-ChORH5JH.mjs → archive-k79AXZhh.mjs} +4 -4
  16. package/dist/{auth-Dltxua89.mjs → auth-CLZuUSzL.mjs} +5 -5
  17. package/dist/{body-Cur4NJt9.mjs → body-Q8iNnt-X.mjs} +3 -3
  18. package/dist/{branches-DchlyU0i.mjs → branches-CjMIMKse.mjs} +4 -7
  19. package/dist/{cancel-BMQa5R1Z.mjs → cancel-H4vYr5Jv.mjs} +4 -4
  20. package/dist/{cancel-task-C5CU1pxU.mjs → cancel-task-p09LCbgs.mjs} +5 -8
  21. package/dist/{card-zyUkr2nS.mjs → card-CEkp1mcI.mjs} +1 -1
  22. package/dist/card-DlVb10D3.mjs +24 -0
  23. package/dist/{card-DZxRmver.mjs → card-voh1k4hl.mjs} +14 -11
  24. package/dist/{cards-SccWvRQD.mjs → cards-DDG6RObF.mjs} +7 -7
  25. package/dist/cli.mjs +567 -68
  26. package/dist/client-toDDqakD.mjs +4093 -0
  27. package/dist/{collection-CfulNRBG.mjs → collection-BxdPxD38.mjs} +1 -1
  28. package/dist/{collection-CGoVLvcD.mjs → collection-DYM0p3Xl.mjs} +1 -1
  29. package/dist/{collection-namespace-GwydWBF3.mjs → collection-namespace-DDI9-HgU.mjs} +2 -2
  30. package/dist/collection-p_sficxo.mjs +20 -0
  31. package/dist/content-translation-BrHOrmj9.mjs +5 -0
  32. package/dist/content-translation-DcTEH_d7.mjs +12 -0
  33. package/dist/{create-CAWytBE5.mjs → create-BLxdMJgQ.mjs} +5 -5
  34. package/dist/{create-BNQ_DytP.mjs → create-BPN1cX7b.mjs} +4 -4
  35. package/dist/{create-CHQx7jq4.mjs → create-BjCpsMQM.mjs} +5 -5
  36. package/dist/{create-CD008jdE.mjs → create-BovrhBQn.mjs} +12 -8
  37. package/dist/{create-DV-Ln5Mo.mjs → create-CVCPD-1F.mjs} +4 -4
  38. package/dist/{create-DJmXXQoq.mjs → create-CVPGOx7u2.mjs} +8 -8
  39. package/dist/{create-Beh-2uoN.mjs → create-Chs5c8vx.mjs} +6 -6
  40. package/dist/{create-BOLwWt8Q.mjs → create-D04fl6ec.mjs} +5 -5
  41. package/dist/{create-C79vErX0.mjs → create-D5mN20oE.mjs} +7 -7
  42. package/dist/{create-DF4QtgDL.mjs → create-D88Im3X22.mjs} +6 -6
  43. package/dist/{create-tQbnuz-I.mjs → create-DQfOV9Sm.mjs} +6 -6
  44. package/dist/{create-CCh_LyW9.mjs → create-DWU4j22P.mjs} +4 -4
  45. package/dist/create-DjP2yUyn.mjs +34 -0
  46. package/dist/{create-CAQV2g6V.mjs → create-Dk6Zm3ZH.mjs} +7 -7
  47. package/dist/{create-zeveFdnd.mjs → create-DkmeJGMy.mjs} +5 -8
  48. package/dist/{create-i14Wv3Tj.mjs → create-TQr3briq.mjs} +4 -4
  49. package/dist/{create-branch-CYo6jZth.mjs → create-branch-Bs6BlkgQ.mjs} +5 -9
  50. package/dist/{csv-B2Jgb1GM.mjs → csv-BsN6FmY-.mjs} +6 -5
  51. package/dist/{current-task-MpBFGttd.mjs → current-task-cCmLLVcv.mjs} +5 -8
  52. package/dist/{dashboard-BHJBoaG7.mjs → dashboard-CpIEKEgu.mjs} +10 -10
  53. package/dist/{dashboard-BCpSq_G-.mjs → dashboard-D0hwTC-f.mjs} +12 -2
  54. package/dist/{dashboard-CsIFFpzK.mjs → dashboard-DgK81azj.mjs} +1 -1
  55. package/dist/{database-B19qlLKZ.mjs → database-C3E9PZSx.mjs} +1 -1
  56. package/dist/{database-C8G6ZKG0.mjs → database-JtHTqSpq.mjs} +1 -1
  57. package/dist/{db-DsfojyeH.mjs → db-BbvcmfWM.mjs} +7 -7
  58. package/dist/{delete-B8e01xAG.mjs → delete-C4_rcfNu.mjs} +5 -5
  59. package/dist/delete-CLdDYdYG.mjs +44 -0
  60. package/dist/{delete-DFmX7jTp.mjs → delete-D13SLwhr.mjs} +5 -5
  61. package/dist/{delete-Ob06PPie.mjs → delete-D3-jMLu5.mjs} +5 -5
  62. package/dist/{delete-BApOjQvl.mjs → delete-DLirF5iq.mjs} +5 -5
  63. package/dist/{delete-Ck0q4Dzp.mjs → delete-JBjvxdIU.mjs} +5 -5
  64. package/dist/{delete-runtime-D74s6vhu.mjs → delete-runtime-BKEzJn22.mjs} +1 -2
  65. package/dist/{delete-table-DuyhGrvA.mjs → delete-table-Gwk7JL5c.mjs} +5 -5
  66. package/dist/{dependencies-Bj3QrGIm.mjs → dependencies-B7vl9Ovb.mjs} +7 -7
  67. package/dist/{dirty-DNYoM6Bp.mjs → dirty-CIZeASXG.mjs} +6 -9
  68. package/dist/{document-Cd2mmqCp.mjs → document-BHpLJbKU.mjs} +5 -0
  69. package/dist/{document-D6OybtP2.mjs → document-CA0Q6lqu.mjs} +1 -1
  70. package/dist/document-ceJW4VuL.mjs +19 -0
  71. package/dist/download-B-krJch0.mjs +25 -0
  72. package/dist/{eid-WTZmDdsr.mjs → eid-C0D92gZW.mjs} +4 -5
  73. package/dist/{events-Bn7jh5lP.mjs → events-CuLeaey6.mjs} +5 -5
  74. package/dist/{export-BjfoZRDJ.mjs → export-DeuLpt3x.mjs} +7 -10
  75. package/dist/{field-Zau6Hc6X.mjs → field-B8Hndt4p.mjs} +5 -5
  76. package/dist/{field-Cr2DPUG9.mjs → field-CcN4oZy6.mjs} +16 -1
  77. package/dist/{field-BPsNa-TO.mjs → field-fDtIrY6D.mjs} +1 -1
  78. package/dist/{fields-CBBa-Prp.mjs → fields-CAchmFh4.mjs} +7 -7
  79. package/dist/{get-CDJFVvhj.mjs → get-BH3Tgfgf.mjs} +4 -4
  80. package/dist/{get-CDMGbgrh.mjs → get-BJOxfbDP.mjs} +4 -4
  81. package/dist/{get-B_xdF1kq.mjs → get-BOjTqIMx.mjs} +6 -6
  82. package/dist/{get-D_h-G9bn.mjs → get-C1BPEbyl.mjs} +6 -6
  83. package/dist/{get-Dmj9Ygz1.mjs → get-C8dcHjd6.mjs} +6 -6
  84. package/dist/{get-DkWO0EI0.mjs → get-CArTALOt.mjs} +6 -6
  85. package/dist/get-CMCAgpxn.mjs +93 -0
  86. package/dist/{get-CnbUCzDM.mjs → get-CjDHpz6A.mjs} +4 -4
  87. package/dist/{get-ByBOq30r.mjs → get-ClNkea9I.mjs} +6 -6
  88. package/dist/{get-DRvsATp-.mjs → get-CvAMxfPD.mjs} +6 -6
  89. package/dist/{get-B7sMgsFs.mjs → get-D8qaSSEH.mjs} +4 -4
  90. package/dist/{get-00lyLv6R.mjs → get-DCvnNk3f.mjs} +6 -6
  91. package/dist/{get-DY03Azx9.mjs → get-DEwfm3Yl.mjs} +5 -8
  92. package/dist/{get-C2-Q3iQ5.mjs → get-DXWrGwWH.mjs} +4 -4
  93. package/dist/get-DbXTkB4u.mjs +32 -0
  94. package/dist/{get-DYO1kywc.mjs → get-DvF9oooq.mjs} +5 -5
  95. package/dist/{get-DdsoHaKH.mjs → get-d055CJ1T.mjs} +4 -4
  96. package/dist/{get-Bz99dAxK.mjs → get-kBTeBtLe.mjs} +6 -6
  97. package/dist/{get-DmpB6J9g.mjs → get-ohue3YrV2.mjs} +6 -6
  98. package/dist/{get-run-Cnux9ln0.mjs → get-run-X6zhp0dW.mjs} +6 -6
  99. package/dist/{get-Dn9ZiSZr.mjs → get-wIZrb7oN.mjs} +6 -6
  100. package/dist/git-sync-BkTmSgdD.mjs +28 -0
  101. package/dist/{git-sync-BDnxPrqU.mjs → git-sync-BwBRmEhE.mjs} +18 -1
  102. package/dist/{git-sync-DxD_ng48.mjs → git-sync-TjX1r_wF.mjs} +1 -1
  103. package/dist/{group-DBM87IgC.mjs → group-YQQ5GIcP.mjs} +2 -2
  104. package/dist/{has-remote-changes-C684Redh.mjs → has-remote-changes-zCtdEGs-.mjs} +5 -8
  105. package/dist/{import-Rmmttboo.mjs → import-DkAy_Xi8.mjs} +7 -10
  106. package/dist/{input-DH9i67x_.mjs → input-DEvkIjGr.mjs} +1 -1
  107. package/dist/{is-dirty-DYeJYhBz.mjs → is-dirty-Dfk2Xf-W.mjs} +3 -6
  108. package/dist/{items-CQlPXBXE.mjs → items-CiSBrc9d.mjs} +7 -7
  109. package/dist/{key-BEhqIzIQ.mjs → key-PYetuQ13.mjs} +1 -1
  110. package/dist/library-BPIzb3K_.mjs +81 -0
  111. package/dist/{library-Bsm5KsFF.mjs → library-FBj2Je-M.mjs} +5 -5
  112. package/dist/{library-DfYAT2Ep.mjs → library-PGCfm0UA.mjs} +1 -1
  113. package/dist/list-9CJczyF5.mjs +60 -0
  114. package/dist/{list-DE9FM957.mjs → list-B6tDzQsv.mjs} +4 -4
  115. package/dist/{list-BtkWNtvY.mjs → list-BDJkJc8s.mjs} +7 -7
  116. package/dist/{list-BzVTHOoH.mjs → list-Br0g0oDR.mjs} +6 -6
  117. package/dist/{list-CNUiF8Z7.mjs → list-C9-2J0Nu.mjs} +6 -6
  118. package/dist/{list-B4hJuMhA.mjs → list-CGjdrAhT.mjs} +7 -7
  119. package/dist/{list-BtmsNOEn.mjs → list-CHOJQ1uR.mjs} +4 -4
  120. package/dist/{list-CKK-s3Ty.mjs → list-CK4S_aDK.mjs} +4 -4
  121. package/dist/{list-C5Zs8nrb.mjs → list-CYONHM9n.mjs} +6 -6
  122. package/dist/{list-CQwOgIlj.mjs → list-CrwbvMEG.mjs} +6 -6
  123. package/dist/{list-BOET6zhP.mjs → list-D6WZmnG_.mjs} +4 -4
  124. package/dist/{list-DMKDsBRd.mjs → list-DD_tjCmP.mjs} +7 -7
  125. package/dist/{list-DF2rvoO1.mjs → list-Dqv3nOEe.mjs} +14 -13
  126. package/dist/{list-CQDprvW0.mjs → list-Hjsg2N8L.mjs} +7 -7
  127. package/dist/{list-CMpoc2TN.mjs → list-M4Twal0d.mjs} +5 -5
  128. package/dist/{list-BpFp9Wre.mjs → list-UbzhJFFn.mjs} +4 -4
  129. package/dist/list-W5y4079U.mjs +35 -0
  130. package/dist/{list-BP3MPq-M.mjs → list-f5HIVoLN.mjs} +4 -4
  131. package/dist/{list-B8nAGwP4.mjs → list-uCAP4vmQ.mjs} +6 -6
  132. package/dist/{login-CGHeSjlP.mjs → login-CIzUMkf3.mjs} +15 -12
  133. package/dist/{logout-DAxOlbv4.mjs → logout-CRm_AaoF.mjs} +3 -4
  134. package/dist/{measure-BsYv0p26.mjs → measure-DPXeIN18.mjs} +6 -6
  135. package/dist/{notification-Fcq1fIPw.mjs → notification-DVrLkjFT.mjs} +1 -1
  136. package/dist/{parameter-DUKR8NXo.mjs → parameter-Celg0wZa.mjs} +1 -1
  137. package/dist/{parameter-values-CJTdqd8c.mjs → parameter-values-rOHoy3k0.mjs} +5 -6
  138. package/dist/{parse-enum-D0Jfm_Bz.mjs → parse-enum-Dc0dMZ3P.mjs} +1 -1
  139. package/dist/{parse-id-C_jmKFaa.mjs → parse-id-CYZAIB58.mjs} +1 -1
  140. package/dist/{parse-ref-ibKVB0J4.mjs → parse-ref-DTDld_LJ.mjs} +1 -1
  141. package/dist/{path-B5gHvrYL.mjs → path-D9_unWc1.mjs} +5 -5
  142. package/dist/{poll-75SvT7Zv.mjs → poll-CZeXepUQ.mjs} +2 -2
  143. package/dist/{preflight-YpPQo-sa.mjs → preflight-BIxRV-bm.mjs} +3 -4
  144. package/dist/{process-DBOOrmET.mjs → process-CTrfxxaC.mjs} +1 -1
  145. package/dist/{publish-DijrxaCW.mjs → publish-N509vd0U.mjs} +9 -9
  146. package/dist/{pulse-BmsDenXm.mjs → pulse-Dz0ocv0l.mjs} +1 -1
  147. package/dist/{pulse-DhG6I9mI.mjs → pulse-x0gFxWfG.mjs} +2 -2
  148. package/dist/{query-Dc__-KJH.mjs → query-JvMjF22L.mjs} +9 -10
  149. package/dist/{query-result-DBDwk8TS.mjs → query-result-E4Q-Gra6.mjs} +1 -1
  150. package/dist/{query-BbqECzmF.mjs → query-yh5Wkfmc.mjs} +11 -18
  151. package/dist/{remove-collection-BOnxYvhj.mjs → remove-collection-B0E0dlZt.mjs} +6 -9
  152. package/dist/{render-CI93iP0I.mjs → render-Tlz6OCMU.mjs} +13 -2
  153. package/dist/{replace-Cq4CxVa-.mjs → replace-BwbYo6-2.mjs} +6 -5
  154. package/dist/{rescan-values-Dr_j416g.mjs → rescan-values-BiMPb5Z5.mjs} +6 -6
  155. package/dist/{run-DdGJ544X.mjs → run-B9aA1aNI.mjs} +26 -14
  156. package/dist/run-D37ntUQo.mjs +50 -0
  157. package/dist/{run-C3DkS6NP.mjs → run-Dbh3nvzF.mjs} +6 -6
  158. package/dist/{runs-CUNWiidL.mjs → runs-BuUzKR-x.mjs} +7 -7
  159. package/dist/{runtime-DiKyBxOw.mjs → runtime-CwhhhwcB.mjs} +946 -246
  160. package/dist/{schema-tables-CV386fnC.mjs → schema-tables-9PvvygPu.mjs} +7 -7
  161. package/dist/{schemas-DM-UqZBQ.mjs → schemas-DqkQI39t.mjs} +5 -5
  162. package/dist/{search-DFBwUc6d.mjs → search-BAXg-EJw.mjs} +2 -1
  163. package/dist/{search-DmGScXs8.mjs → search-BjAwR-oP.mjs} +6 -6
  164. package/dist/{segment-BzUGM2Fr.mjs → segment-1nBcugv8.mjs} +6 -6
  165. package/dist/{selectors-DGDn0Hto.mjs → selectors-DFNdyhPn.mjs} +3 -3
  166. package/dist/{send-CVxxEpDB.mjs → send-D4tYN3aN.mjs} +4 -4
  167. package/dist/{set-DFolTjbd.mjs → set-D_Mh2eVO.mjs} +5 -5
  168. package/dist/{set-active-BD8L1lPX.mjs → set-active-jY5VZsO8.mjs} +5 -5
  169. package/dist/{setting-DyhaeICs.mjs → setting-9ULb5wjN.mjs} +4 -4
  170. package/dist/{setup-BbDQN8fe.mjs → setup-DMaIuuCV.mjs} +4 -4
  171. package/dist/{signal-CMd0EFUa.mjs → signal-k7cm5N6h.mjs} +11 -2
  172. package/dist/skill-list-Bucy7UE2.mjs +76 -0
  173. package/dist/{skills--vK6J-e4.mjs → skills-Dyfqgobg.mjs} +3 -3
  174. package/dist/skills-PjjRtYqi.mjs +351 -0
  175. package/dist/snippet-DNoTIGAs.mjs +19 -0
  176. package/dist/{stash-D0S4JmAz.mjs → stash-C6BEM6_u.mjs} +7 -11
  177. package/dist/{status-BhswxJL1.mjs → status-DiP093Vm.mjs} +11 -9
  178. package/dist/{status-hL1am-HV.mjs → status-wAg5ajzM.mjs} +12 -11
  179. package/dist/stream-McixcoUl.mjs +7 -0
  180. package/dist/{subscription-_d5fB45F.mjs → subscription-CEeI0pSr.mjs} +6 -6
  181. package/dist/{subscriptions-s4TF6Ax3.mjs → subscriptions-B9cMNuIS.mjs} +7 -7
  182. package/dist/{summary-CsPvcUwW.mjs → summary-D0NP2NoT.mjs} +6 -6
  183. package/dist/{sync-schema-DaZ_MV-u.mjs → sync-schema-BgJ6KEqa.mjs} +7 -7
  184. package/dist/{sync-task-BACcrs0i.mjs → sync-task-BXeWuARG.mjs} +1 -1
  185. package/dist/{table-DYoC1kPn.mjs → table-9bTG6zSa.mjs} +5 -5
  186. package/dist/{table-CsIJNPFf.mjs → table-C6h4tIRw.mjs} +1 -1
  187. package/dist/{table-CeeTJgQb.mjs → table-DfuY0N8e.mjs} +51 -4
  188. package/dist/timeline-Ck53UgDh.mjs +21 -0
  189. package/dist/{timeline-event-CNQdCTDg.mjs → timeline-event-POmQ2TD2.mjs} +6 -6
  190. package/dist/transform-BC39AgQF.mjs +28 -0
  191. package/dist/{transform-DoTyyXAu.mjs → transform-CtqB1WYo.mjs} +2 -2
  192. package/dist/{transform-D3QX0jxA.mjs → transform-DiW7bREn.mjs} +68 -5
  193. package/dist/{transform-job-50GZHhKH.mjs → transform-job-AaMZRxAq.mjs} +1 -1
  194. package/dist/{transform-job-DRrK28IH.mjs → transform-job-CCguL6LP.mjs} +41 -4
  195. package/dist/transform-job-D-zUFmZU.mjs +22 -0
  196. package/dist/{transform-tag-_tgwlsdB.mjs → transform-tag-CP7FRU5G.mjs} +5 -5
  197. package/dist/transform-test-BjjCQ2xm.mjs +169 -0
  198. package/dist/transform-test-CKNQS_kC.mjs +16 -0
  199. package/dist/transform-test-gzDcbypy.mjs +25 -0
  200. package/dist/{transforms-oU4zizbO.mjs → transforms-DDSNP4eL.mjs} +7 -7
  201. package/dist/{tree-CH-f3bjP.mjs → tree-CAnMS2dm.mjs} +4 -5
  202. package/dist/{unpublish-BUl9RU5C.mjs → unpublish-DF1XQMWJ.mjs} +4 -7
  203. package/dist/{update-BZPllQoR.mjs → update-BS1yiwOO.mjs} +5 -5
  204. package/dist/{update-CO4m4wH3.mjs → update-Bb89y-0M.mjs} +8 -8
  205. package/dist/{update-C4YJQFDS.mjs → update-BbiVvdm1.mjs} +7 -7
  206. package/dist/{update-BCS5FxKr.mjs → update-BcdLQu7-.mjs} +9 -9
  207. package/dist/{update-cYkvbqK8.mjs → update-BjcWwrPc.mjs} +5 -5
  208. package/dist/{update-tX9mKBN_.mjs → update-BoJJ6Gel.mjs} +9 -9
  209. package/dist/{update-CHNSUHK4.mjs → update-C09GGTjN.mjs} +5 -5
  210. package/dist/{update-BzMDeZiU.mjs → update-C33R41eM.mjs} +7 -7
  211. package/dist/{update-CmDTljK-.mjs → update-C6KQZMDF.mjs} +7 -7
  212. package/dist/{update-bD_Jh5-s.mjs → update-CFqdElFO.mjs} +6 -6
  213. package/dist/{update-CVPAwJaH.mjs → update-CHsXoUJQ.mjs} +6 -6
  214. package/dist/update-CaJO1rWk.mjs +41 -0
  215. package/dist/{update-CvOO8TED.mjs → update-CmXGZPCR.mjs} +7 -7
  216. package/dist/{update-D-NE60AV.mjs → update-DFJSD3_l.mjs} +7 -7
  217. package/dist/{update-Nfi44RrE.mjs → update-DOeBAoul.mjs} +6 -6
  218. package/dist/{update-BiFDBcEH.mjs → update-DiowA7ud.mjs} +5 -5
  219. package/dist/{update-dashcard-C3TuYO_k.mjs → update-dashcard-DSL6Bogg.mjs} +7 -7
  220. package/dist/{upgrade-DXMV4AyP.mjs → upgrade-CBxr91bH.mjs} +6 -8
  221. package/dist/upload-C3z5ZaXA.mjs +24 -0
  222. package/dist/upload-CSHcnonI.mjs +13 -0
  223. package/dist/upload-DTyF-p8X.mjs +39 -0
  224. package/dist/upload-Do2PBSeH.mjs +23 -0
  225. package/dist/{uuid-BJkDWj9p.mjs → uuid-CwEbjDp8.mjs} +3 -4
  226. package/dist/{validate-BWchyW0V.mjs → validate-EAB-1EkK.mjs} +1 -1
  227. package/dist/{validate-query-DaGYSmpQ.mjs → validate-query-CQG86147.mjs} +2 -3
  228. package/dist/{values-Dxf1JEoA.mjs → values-69IZEVXu.mjs} +6 -6
  229. package/dist/{verify-K96rItG5.mjs → verify-Dg5YBI0l.mjs} +3 -18
  230. package/dist/{wait-DoMDH226.mjs → wait-DVXEJXd3.mjs} +7 -10
  231. package/dist/{wait-flags-DWEF9tX4.mjs → wait-flags-CkRgnfww.mjs} +2 -2
  232. package/dist/{window-BkvrP0gB.mjs → window-DSb1tqSe.mjs} +1 -1
  233. package/package.json +1 -1
  234. package/skill-data/core/SKILL.md +31 -14
  235. package/skill-data/dashboard/SKILL.md +2 -2
  236. package/skill-data/data-workflow/references/building-clean-tables.md +6 -2
  237. package/skill-data/data-workflow/references/reusable-definitions.md +11 -3
  238. package/skill-data/document/SKILL.md +4 -1
  239. package/skill-data/git-sync/SKILL.md +5 -0
  240. package/skill-data/mbql/SKILL.md +1 -1
  241. package/skill-data/mbql/references/operators.md +20 -15
  242. package/skill-data/metadata/SKILL.md +1 -1
  243. package/skill-data/metadata/references/semantic-types.md +7 -1
  244. package/skill-data/native-sql/references/template-tags.md +6 -2
  245. package/skill-data/notification/SKILL.md +7 -1
  246. package/skill-data/transform/SKILL.md +75 -3
  247. package/skill-data/transform-test-plan/SKILL.md +171 -0
  248. package/skill-data/transform-test-plan/references/checklist.md +81 -0
  249. package/skill-data/transform-test-plan/references/checks.md +259 -0
  250. package/skill-data/visualization/SKILL.md +11 -3
  251. package/skill-data/visualization/references/settings.md +6 -4
  252. package/skills/metabase-cli/SKILL.md +1 -1
  253. package/dist/card-CHI2bmds.mjs +0 -24
  254. package/dist/client-BqhzKdLM.mjs +0 -2194
  255. package/dist/collection-CY0AB99E.mjs +0 -20
  256. package/dist/document-BbskZPTT.mjs +0 -19
  257. package/dist/get-CvI--9S_.mjs +0 -80
  258. package/dist/git-sync-MQQYRYLg.mjs +0 -28
  259. package/dist/library-ClLgrAXy.mjs +0 -19
  260. package/dist/list-UhpKG6_m.mjs +0 -98
  261. package/dist/network-error-CEb9ymDW.mjs +0 -423
  262. package/dist/predicates-Bkm2IoeX.mjs +0 -170
  263. package/dist/skills-DTCrMcix.mjs +0 -216
  264. package/dist/snippet-DRwKb2x7.mjs +0 -19
  265. package/dist/timeline-xlDbEKWg.mjs +0 -21
  266. package/dist/transform-Bs0EWijQ.mjs +0 -28
  267. package/dist/transform-job-BcLChRup.mjs +0 -22
  268. package/dist/upload-CH632qW6.mjs +0 -46
  269. package/dist/upload-Dey_8rLf.mjs +0 -13
@@ -1,2194 +0,0 @@
1
- import { a as InternalError, c as ResponseShapeError, d as ValidationError, f as errorMessage, i as ConfigError, l as TimeoutError, s as NetworkError } from "./predicates-Bkm2IoeX.mjs";
2
- import { n as Notification, r as NotificationCardPayload, t as CARD_PAYLOAD_TYPE } from "./notification-DaA4bBHW.mjs";
3
- import { a as isRetryableStatus, c as normalizeUrl, d as credentialSecrets, g as parseJsonOrPlain, h as parseJson, l as assertCredentialHeaderSafe, m as JSON_CONTENT_TYPE, n as isConnectionClosed, r as HttpError, t as buildNetworkError, u as credentialAuthHeader } from "./network-error-CEb9ymDW.mjs";
4
- import { n as throwIfAborted, t as combineAborts } from "./signal-CMd0EFUa.mjs";
5
- import { s as FieldValues, t as Field } from "./field-Cr2DPUG9.mjs";
6
- import { r as ParameterValues } from "./parameter-DUKR8NXo.mjs";
7
- import { o as CardQueryResult, t as Card } from "./card-DZxRmver.mjs";
8
- import { f as CollectionTreeNode, o as CollectionItem, r as Collection } from "./collection-CfulNRBG.mjs";
9
- import { i as DashboardDetail, s as Dashcard, t as Dashboard } from "./dashboard-BCpSq_G-.mjs";
10
- import { i as TableQueryMetadata, t as Table } from "./table-CeeTJgQb.mjs";
11
- import { t as Database } from "./database-C8G6ZKG0.mjs";
12
- import { r as pollUntil } from "./poll-75SvT7Zv.mjs";
13
- import { t as Document } from "./document-Cd2mmqCp.mjs";
14
- import { i as EidTranslateResult } from "./eid-translation-zEHtr5Oc.mjs";
15
- import { f as isSyncTaskTerminal, l as SyncTask, n as SyncDirtyItem, o as SyncRemoteChanges, s as SyncSettingsUpdateResult, t as SyncBranchCreated } from "./git-sync-BDnxPrqU.mjs";
16
- import { t as Library } from "./library-ClLgrAXy.mjs";
17
- import { t as Measure } from "./measure-CtfjqJFP.mjs";
18
- import { t as Pulse } from "./pulse-BmsDenXm.mjs";
19
- import { r as SearchResult } from "./search-DFBwUc6d.mjs";
20
- import { t as Segment } from "./segment-OsrbUDzw.mjs";
21
- import { t as Setting } from "./setting-DTiLCW8g.mjs";
22
- import { n as SetupResult } from "./setup-CO7QV-ao.mjs";
23
- import { t as Snippet } from "./snippet-CyKAgIZl.mjs";
24
- import { i as TimelineEvent, t as Timeline } from "./timeline-CCSU2qOS.mjs";
25
- import { i as TransformRun, l as isTransformRunFailed, t as Transform, u as isTransformRunTerminal } from "./transform-D3QX0jxA.mjs";
26
- import { a as TransformJobRunResult, n as TransformJobActiveResult, t as TransformJob } from "./transform-job-DRrK28IH.mjs";
27
- import { t as TransformTag } from "./transform-tag-CcElGp3C.mjs";
28
- import { t as UploadResult } from "./upload-DAtxBBms.mjs";
29
- import { z } from "zod";
30
- import { setTimeout } from "node:timers/promises";
31
- //#region \0rolldown/runtime.js
32
- var __defProp = Object.defineProperty;
33
- var __exportAll = (all, no_symbols) => {
34
- let target = {};
35
- for (var name in all) __defProp(target, name, {
36
- get: all[name],
37
- enumerable: true
38
- });
39
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
40
- return target;
41
- };
42
- //#endregion
43
- //#region ../client/src/http/response-shape.ts
44
- const NO_SERVER_TAG = async () => null;
45
- async function parseJsonResponse(text, schema, context) {
46
- try {
47
- return parseJson(text, schema, { source: context.url });
48
- } catch (error) {
49
- if (error instanceof ValidationError) throw ResponseShapeError.fromZodIssues({
50
- kind: "zod",
51
- method: context.method,
52
- url: context.url,
53
- status: context.status,
54
- zodIssues: error.developerDetail.zodIssues,
55
- serverTag: await context.getServerTag()
56
- });
57
- throw error;
58
- }
59
- }
60
- //#endregion
61
- //#region ../client/src/http/retry.ts
62
- const BASE_DELAY_MS = 250;
63
- const MAX_DELAY_MS = 8e3;
64
- const MS_PER_SECOND = 1e3;
65
- function backoffDelay({ attempt, retryAfterHeader }) {
66
- const fromHeader = parseRetryAfter(retryAfterHeader);
67
- if (fromHeader !== null) return fromHeader;
68
- return Math.min(MAX_DELAY_MS, BASE_DELAY_MS * 2 ** attempt);
69
- }
70
- function parseRetryAfter(header) {
71
- if (!header) return null;
72
- const numeric = Number(header);
73
- if (Number.isFinite(numeric) && numeric >= 0) return Math.round(numeric * MS_PER_SECOND);
74
- const dateMs = Date.parse(header);
75
- if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
76
- return null;
77
- }
78
- function sleep(ms, signal) {
79
- return setTimeout(ms, void 0, { signal });
80
- }
81
- async function runWithRetries(attempt, signal) {
82
- let attemptIndex = 0;
83
- while (true) {
84
- const outcome = await attempt(attemptIndex);
85
- if (outcome.kind === "success") return outcome.response;
86
- await sleep(outcome.delayMs, signal);
87
- attemptIndex += 1;
88
- }
89
- }
90
- //#endregion
91
- //#region ../client/src/http/transport.ts
92
- const UNAUTHORIZED_STATUS = 401;
93
- const DEFAULT_TIMEOUT_MS = 3e4;
94
- const OCTET_STREAM_CONTENT_TYPE = "application/octet-stream";
95
- const TEXT_CONTENT_TYPE_PREFIX = "text/";
96
- const ERROR_BODY_BYTE_CAP = 64 * 1024;
97
- const IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
98
- "GET",
99
- "HEAD",
100
- "OPTIONS"
101
- ]);
102
- function createTransport(config, options) {
103
- const baseUrl = normalizeUrl(config.url);
104
- assertCredentialHeaderSafe(config.credential);
105
- const fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
106
- const getServerTag = options.getServerTag ?? NO_SERVER_TAG;
107
- const refreshCredential = options.refreshCredential;
108
- let credential = config.credential;
109
- const knownSecrets = new Set(credentialSecrets(credential));
110
- const redactionContext = { knownSecrets };
111
- let refreshInFlight = null;
112
- function tryRefreshCredential() {
113
- const refresh = refreshCredential;
114
- if (credential.kind !== "oauth" || refresh === void 0) return Promise.resolve(false);
115
- refreshInFlight ??= refreshOnce(refresh).finally(() => {
116
- refreshInFlight = null;
117
- });
118
- return refreshInFlight;
119
- }
120
- async function refreshOnce(refresh) {
121
- const next = await refresh();
122
- if (next === null) return false;
123
- credential = next;
124
- for (const secret of credentialSecrets(next)) knownSecrets.add(secret);
125
- return true;
126
- }
127
- async function attemptOnce(prepared, attempt) {
128
- const hasRetriesLeft = attempt < prepared.retries;
129
- const timeoutSignal = AbortSignal.timeout(prepared.timeoutMs);
130
- const combined = combineAborts(timeoutSignal, prepared.cancelSignal);
131
- let response;
132
- try {
133
- response = await fetchImpl(prepared.url, {
134
- method: prepared.method,
135
- headers: prepared.headers,
136
- body: prepared.body,
137
- signal: combined
138
- });
139
- } catch (error) {
140
- throwIfAborted(prepared.cancelSignal);
141
- const isStaleSocketFirstTry = attempt === 0 && isConnectionClosed(error);
142
- if (prepared.idempotent && (hasRetriesLeft || isStaleSocketFirstTry)) return {
143
- kind: "retry",
144
- delayMs: backoffDelay({ attempt })
145
- };
146
- if (timeoutSignal.aborted) throw new TimeoutError(`Request timed out after ${prepared.timeoutMs}ms`, {
147
- kind: "http",
148
- method: prepared.method,
149
- url: prepared.url,
150
- timeoutMs: prepared.timeoutMs
151
- });
152
- throw buildNetworkError(error, prepared.method, prepared.url);
153
- }
154
- const canRetryStatus = hasRetriesLeft && prepared.idempotent;
155
- if (!response.ok && isRetryableStatus(response.status) && canRetryStatus) {
156
- const retryAfter = response.headers.get("Retry-After");
157
- response.body?.cancel().catch(() => void 0);
158
- return {
159
- kind: "retry",
160
- delayMs: backoffDelay({
161
- attempt,
162
- retryAfterHeader: retryAfter
163
- })
164
- };
165
- }
166
- if (!response.ok) {
167
- const rawBody = await readBodyForError(response);
168
- const serverTag = await getServerTag();
169
- throw new HttpError({
170
- status: response.status,
171
- statusText: response.statusText,
172
- method: prepared.method,
173
- url: prepared.url,
174
- responseHeaders: response.headers,
175
- rawBody,
176
- serverTag,
177
- redactionContext
178
- });
179
- }
180
- assertContentType(response, prepared);
181
- return {
182
- kind: "success",
183
- response
184
- };
185
- }
186
- async function executeRaw(prepared) {
187
- try {
188
- return await runWithRetries((attempt) => attemptOnce(prepared, attempt), prepared.cancelSignal);
189
- } catch (error) {
190
- throwIfAborted(prepared.cancelSignal);
191
- throw error;
192
- }
193
- }
194
- async function executeWithAuthRefresh(path, opts) {
195
- const prepared = prepare(path, opts);
196
- try {
197
- return {
198
- response: await executeRaw(prepared),
199
- prepared
200
- };
201
- } catch (error) {
202
- if (error instanceof HttpError && error.status === UNAUTHORIZED_STATUS) {
203
- if (await tryRefreshCredential()) {
204
- const retried = prepare(path, opts);
205
- return {
206
- response: await executeRaw(retried),
207
- prepared: retried
208
- };
209
- }
210
- }
211
- throw error;
212
- }
213
- }
214
- function prepare(path, opts = {}) {
215
- const method = opts.method ?? "GET";
216
- const expectContentType = opts.expectContentType ?? "json";
217
- const url = buildUrl(baseUrl, path, opts.query);
218
- const headers = new Headers();
219
- const auth = credentialAuthHeader(credential);
220
- headers.set(auth.name, auth.value);
221
- headers.set("accept", acceptHeader(expectContentType));
222
- headers.set("user-agent", options.userAgent);
223
- let body = null;
224
- if (opts.body !== void 0 && opts.body !== null) if (typeof opts.body === "string" || opts.body instanceof URLSearchParams) body = opts.body;
225
- else if (opts.body instanceof FormData || opts.body instanceof ReadableStream) body = opts.body;
226
- else if (opts.body instanceof Uint8Array) {
227
- body = opts.body;
228
- headers.set("content-type", OCTET_STREAM_CONTENT_TYPE);
229
- } else {
230
- body = JSON.stringify(opts.body);
231
- headers.set("content-type", JSON_CONTENT_TYPE);
232
- }
233
- return {
234
- url,
235
- method,
236
- headers,
237
- body,
238
- expectContentType,
239
- retries: opts.retries ?? 3,
240
- idempotent: opts.idempotent ?? IDEMPOTENT_METHODS.has(method),
241
- timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
242
- cancelSignal: combineAborts(opts.signal, options.signal)
243
- };
244
- }
245
- return {
246
- async requestRaw(path, opts) {
247
- return (await executeWithAuthRefresh(path, opts ?? {})).response;
248
- },
249
- async requestParsed(schema, path, opts) {
250
- const { response, prepared } = await executeWithAuthRefresh(path, {
251
- ...opts,
252
- expectContentType: "json"
253
- });
254
- return parseJsonResponse(await response.text(), schema, {
255
- method: prepared.method,
256
- url: prepared.url,
257
- status: response.status,
258
- getServerTag
259
- });
260
- },
261
- async requestStream(path, opts) {
262
- const { response, prepared } = await executeWithAuthRefresh(path, {
263
- ...opts,
264
- expectContentType: opts?.expectContentType ?? "binary"
265
- });
266
- if (!response.body) throw new NetworkError("Response had no body to stream", {
267
- method: prepared.method,
268
- url: prepared.url,
269
- cause: "missing body"
270
- });
271
- return response.body;
272
- }
273
- };
274
- }
275
- function buildUrl(baseUrl, path, query) {
276
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
277
- const target = new URL(baseUrl + normalizedPath);
278
- if (query) for (const [key, value] of Object.entries(query)) {
279
- if (value === void 0) continue;
280
- if (Array.isArray(value)) for (const entry of value) target.searchParams.append(key, String(entry));
281
- else target.searchParams.append(key, String(value));
282
- }
283
- return target.toString();
284
- }
285
- function acceptHeader(expected) {
286
- if (expected === "json") return JSON_CONTENT_TYPE;
287
- if (expected === "text") return "text/*";
288
- return "*/*";
289
- }
290
- function assertContentType(response, prepared) {
291
- if (prepared.expectContentType === "binary") return;
292
- const contentType = response.headers.get("content-type");
293
- if (contentType === null) throwContentTypeMismatch(response, prepared, prepared.expectContentType);
294
- if (prepared.expectContentType === "json" && !contentType.includes("application/json")) throwContentTypeMismatch(response, prepared, "json");
295
- if (prepared.expectContentType === "text" && !contentType.startsWith(TEXT_CONTENT_TYPE_PREFIX)) throwContentTypeMismatch(response, prepared, "text");
296
- }
297
- function throwContentTypeMismatch(response, prepared, expected) {
298
- const actual = response.headers.get("content-type") ?? "no content-type";
299
- throw new HttpError({
300
- status: response.status,
301
- statusText: response.statusText,
302
- method: prepared.method,
303
- url: prepared.url,
304
- responseHeaders: response.headers,
305
- rawBody: null,
306
- overrideUserMessage: `Expected ${expected} response but got ${actual}`
307
- });
308
- }
309
- async function readBodyForError(response) {
310
- try {
311
- return Buffer.from(await response.arrayBuffer()).subarray(0, ERROR_BODY_BYTE_CAP).toString("utf8");
312
- } catch (error) {
313
- return `[body read failed: ${errorMessage(error)}]`;
314
- }
315
- }
316
- //#endregion
317
- //#region ../client/src/resources/card.ts
318
- const CardApiList = z.array(Card);
319
- function cardResource(transport) {
320
- /** List cards. `f` picks a server-side preset; `model_id` scopes the presets that need an id. */
321
- async function list(params = {}, options = {}) {
322
- return {
323
- data: await transport.requestParsed(CardApiList, "/api/card", {
324
- ...options,
325
- query: {
326
- f: params.f,
327
- model_id: params.model_id
328
- }
329
- }),
330
- total: null
331
- };
332
- }
333
- /** Get one card by id. */
334
- async function get(id, options = {}) {
335
- return transport.requestParsed(Card, `/api/card/${id}`, { ...options });
336
- }
337
- /** Create a card — a question, a model, or a metric — from a full card body. */
338
- async function create(params, options = {}) {
339
- return transport.requestParsed(Card, "/api/card", {
340
- ...options,
341
- method: "POST",
342
- body: params
343
- });
344
- }
345
- /** Update a card by id, patching only the fields the body carries. */
346
- async function update(id, params, options = {}) {
347
- return transport.requestParsed(Card, `/api/card/${id}`, {
348
- ...options,
349
- method: "PUT",
350
- body: params
351
- });
352
- }
353
- /** Archive (soft-delete) a card by id. Metabase models this as an update, not its own endpoint. */
354
- async function archive(id, options = {}) {
355
- return update(id, { archived: true }, options);
356
- }
357
- /** Run a saved card and return the query result envelope. */
358
- async function query(id, params, options = {}) {
359
- return transport.requestParsed(CardQueryResult, `/api/card/${id}/query`, {
360
- ...options,
361
- method: "POST",
362
- body: { parameters: params.parameters }
363
- });
364
- }
365
- /**
366
- * Run a saved card and stream its result as a download. Unlike `query`, this endpoint takes a
367
- * form-encoded body and answers bytes, so a caller consumes the stream rather than a value.
368
- */
369
- async function exportQuery(id, format, params, options = {}) {
370
- const body = new URLSearchParams({
371
- parameters: JSON.stringify(params.parameters),
372
- format_rows: String(params.format_rows),
373
- pivot_results: String(params.pivot_results)
374
- });
375
- return transport.requestStream(`/api/card/${id}/query/${format}`, {
376
- ...options,
377
- method: "POST",
378
- body
379
- });
380
- }
381
- return {
382
- list,
383
- get,
384
- create,
385
- update,
386
- archive,
387
- query,
388
- exportQuery
389
- };
390
- }
391
- async function* paginatePages(client, path, itemSchema, opts = {}) {
392
- const envelopeSchema = paginatedEnvelopeSchema(itemSchema);
393
- const pageSize = opts.pageSize ?? 50;
394
- if (!Number.isInteger(pageSize) || pageSize < 1) throw new InternalError(`pageSize must be an integer of at least 1, got ${pageSize}`);
395
- const start = opts.offset ?? 0;
396
- const max = opts.max ?? Number.POSITIVE_INFINITY;
397
- let taken = 0;
398
- let previousHead = null;
399
- while (taken < max) {
400
- const remaining = max - taken;
401
- const limit = Math.min(pageSize, remaining);
402
- const offset = start + taken;
403
- const envelope = await client.requestParsed(envelopeSchema, path, {
404
- query: {
405
- ...opts.query,
406
- limit,
407
- offset
408
- },
409
- ...opts.signal !== void 0 && { signal: opts.signal }
410
- });
411
- const items = envelope.data.length > remaining ? envelope.data.slice(0, remaining) : envelope.data;
412
- const total = envelope.total ?? null;
413
- const head = items.length === 0 ? null : JSON.stringify(items[0]);
414
- if (head !== null && head === previousHead) throw new ConfigError(`the endpoint returned the same first row at offset ${offset} as at the previous offset; it is ignoring the offset parameter, so paging cannot advance`);
415
- previousHead = head;
416
- yield {
417
- items,
418
- total
419
- };
420
- if (items.length === 0) return;
421
- const consumed = taken + items.length;
422
- if (total !== null && start + consumed === total) return;
423
- taken = consumed;
424
- }
425
- }
426
- function paginatedEnvelopeSchema(itemSchema) {
427
- return z.object({
428
- data: z.array(itemSchema),
429
- total: z.number().int().nonnegative().nullable().optional(),
430
- limit: z.number().int().nonnegative().optional(),
431
- offset: z.number().int().nonnegative().optional()
432
- }).loose();
433
- }
434
- //#endregion
435
- //#region ../client/src/resources/collection.ts
436
- const CollectionApiList = z.array(Collection);
437
- const CollectionTreeApiList = z.array(CollectionTreeNode);
438
- const COLLECTION_LIST_QUERY = {
439
- all: {},
440
- archived: { archived: true },
441
- personal: { "personal-only": true }
442
- };
443
- const DEFAULT_LIST_FILTER = "all";
444
- function refPath(ref) {
445
- return encodeURIComponent(ref);
446
- }
447
- /**
448
- * List collections including the Library and its children, parsing each through the caller's own
449
- * projection. `Collection` pins `type`, `namespace` and `authority_level` to closed enums, so a
450
- * consumer reading a few fields off every collection on the instance narrows here: one collection
451
- * carrying a server value outside those sets then costs nothing to a caller that never reads the
452
- * field.
453
- */
454
- async function listCollectionsWithLibrary(transport, schema, options = {}) {
455
- return transport.requestParsed(z.array(schema), "/api/collection", {
456
- ...options,
457
- query: { "include-library": true }
458
- });
459
- }
460
- function collectionResource(transport) {
461
- /** List collections. `filter` picks a server-side preset: everything, archived, or personal. */
462
- async function list(params = {}, options = {}) {
463
- return {
464
- data: await transport.requestParsed(CollectionApiList, "/api/collection", {
465
- ...options,
466
- query: COLLECTION_LIST_QUERY[params.filter ?? DEFAULT_LIST_FILTER]
467
- }),
468
- total: null
469
- };
470
- }
471
- /**
472
- * List collections including the Library and its children, which the plain listing omits.
473
- * The Library's own children carry neither `type` nor `is_remote_synced`, so this is where a
474
- * caller resolves both.
475
- */
476
- async function listWithLibrary(options = {}) {
477
- return {
478
- data: await listCollectionsWithLibrary(transport, Collection, options),
479
- total: null
480
- };
481
- }
482
- /** Get one collection by id, entity id, or the `root`/`trash` alias. */
483
- async function get(ref, options = {}) {
484
- return transport.requestParsed(Collection, `/api/collection/${refPath(ref)}`, { ...options });
485
- }
486
- /** Create a new collection. */
487
- async function create(params, options = {}) {
488
- return transport.requestParsed(Collection, "/api/collection", {
489
- ...options,
490
- method: "POST",
491
- body: params
492
- });
493
- }
494
- /** Update a collection, patching only the fields the body carries. */
495
- async function update(ref, params, options = {}) {
496
- return transport.requestParsed(Collection, `/api/collection/${refPath(ref)}`, {
497
- ...options,
498
- method: "PUT",
499
- body: params
500
- });
501
- }
502
- /** Archive (soft-delete) a collection. Metabase models this as an update, not its own endpoint. */
503
- async function archive(ref, options = {}) {
504
- return update(ref, { archived: true }, options);
505
- }
506
- /**
507
- * Walk the items inside a collection one page at a time. This endpoint pages on the server, so
508
- * the caller consumes pages rather than a single list and decides how far to pull.
509
- */
510
- function itemPages(ref, params = {}, options = {}) {
511
- return paginatePages(transport, `/api/collection/${refPath(ref)}/items`, CollectionItem, {
512
- query: {
513
- models: params.models,
514
- archived: params.archived,
515
- pinned_state: params.pinned_state
516
- },
517
- ...options.offset !== void 0 && { offset: options.offset },
518
- ...options.max !== void 0 && { max: options.max },
519
- ...options.pageSize !== void 0 && { pageSize: options.pageSize },
520
- ...options.signal !== void 0 && { signal: options.signal }
521
- });
522
- }
523
- /** Fetch the collection hierarchy as a forest of nested nodes. */
524
- async function tree(options = {}) {
525
- return {
526
- data: await transport.requestParsed(CollectionTreeApiList, "/api/collection/tree", { ...options }),
527
- total: null
528
- };
529
- }
530
- return {
531
- list,
532
- listWithLibrary,
533
- get,
534
- create,
535
- update,
536
- archive,
537
- itemPages,
538
- tree
539
- };
540
- }
541
- //#endregion
542
- //#region ../client/src/resources/dashboard.ts
543
- const DashboardApiList = z.array(Dashboard);
544
- const PreflightDashcard = z.looseObject({ card_id: z.number().int().nullable().optional() });
545
- function dashboardResource(transport) {
546
- const card = cardResource(transport);
547
- /** List dashboards. `f` picks a server-side preset. */
548
- async function list(params = {}, options = {}) {
549
- return {
550
- data: await transport.requestParsed(DashboardApiList, "/api/dashboard", {
551
- ...options,
552
- query: { f: params.f }
553
- }),
554
- total: null
555
- };
556
- }
557
- /** Get one dashboard by id, with its dashcards, tabs and parameters. */
558
- async function get(id, options = {}) {
559
- return transport.requestParsed(DashboardDetail, `/api/dashboard/${id}`, { ...options });
560
- }
561
- /**
562
- * Create a dashboard. The endpoint accepts no dashcards or tabs — a follow-up `update` is what
563
- * puts content on a fresh dashboard.
564
- */
565
- async function create(params, options = {}) {
566
- return transport.requestParsed(Dashboard, "/api/dashboard", {
567
- ...options,
568
- method: "POST",
569
- body: params
570
- });
571
- }
572
- /**
573
- * Update a dashboard by id, patching only the fields the body carries. `dashcards` and `tabs` are
574
- * full replacements: whatever the body omits is deleted from the dashboard.
575
- */
576
- async function update(id, params, options = {}) {
577
- return transport.requestParsed(DashboardDetail, `/api/dashboard/${id}`, {
578
- ...options,
579
- method: "PUT",
580
- body: params
581
- });
582
- }
583
- /**
584
- * Archive (soft-delete) a dashboard by id. Metabase models this as an update, not its own
585
- * endpoint. The answer is read as `Dashboard` rather than the `DashboardDetail` `update` returns:
586
- * an archive is a state change on the dashboard itself, and its dashcards are not part of it.
587
- */
588
- async function archive(id, options = {}) {
589
- return transport.requestParsed(Dashboard, `/api/dashboard/${id}`, {
590
- ...options,
591
- method: "PUT",
592
- body: { archived: true }
593
- });
594
- }
595
- /**
596
- * Patch one dashcard on a dashboard. Metabase exposes no dashcard endpoint and its dashboard PUT
597
- * is a full replace of `dashcards`, so the patch is read-modify-written over the dashboard as it
598
- * currently stands.
599
- */
600
- async function updateDashcard(dashboardId, dashcardId, params, options = {}) {
601
- const dashboard = await get(dashboardId, options);
602
- const target = dashboard.dashcards.find((dashcard) => dashcard.id === dashcardId);
603
- if (target === void 0) throw new ConfigError(`dashcard ${dashcardId} not found on dashboard ${dashboardId}`);
604
- const patched = Dashcard.parse({
605
- ...target,
606
- ...params
607
- });
608
- const refreshed = (await update(dashboardId, { dashcards: dashboard.dashcards.map((dashcard) => stripEntityId(dashcard.id === dashcardId ? patched : dashcard)) }, options)).dashcards.find((dashcard) => dashcard.id === dashcardId);
609
- if (refreshed === void 0) throw new Error(`PUT /api/dashboard/${dashboardId}: dashcard ${dashcardId} missing from response`);
610
- return refreshed;
611
- }
612
- /**
613
- * Check every card a `dashcards` body references before writing it, through `GET /api/card/{id}`
614
- * once per distinct id. Reports one issue per reference whose card is missing, archived, or
615
- * unreadable, so an empty result means the body is safe to send; an id the server answers for in
616
- * any other way propagates as the failure it was.
617
- */
618
- async function checkCardReferences(dashcards, options = {}) {
619
- const grouped = groupByCardId(collectCardReferences(dashcards));
620
- return (await Promise.all(Array.from(grouped.entries()).map(async ([cardId, references]) => ({
621
- references,
622
- problem: await inspectCard(cardId, options)
623
- })))).flatMap((check) => {
624
- const problem = check.problem;
625
- if (problem === null) return [];
626
- return check.references.map((reference) => ({
627
- ...reference,
628
- problem
629
- }));
630
- });
631
- }
632
- async function inspectCard(cardId, options) {
633
- try {
634
- return (await card.get(cardId, options)).archived ? { reason: "archived" } : null;
635
- } catch (error) {
636
- if (!(error instanceof HttpError)) throw error;
637
- if (error.kind === "resource-missing") return { reason: "missing" };
638
- if (error.kind === "auth") return {
639
- reason: "unreadable",
640
- detail: error.userMessage
641
- };
642
- throw error;
643
- }
644
- }
645
- /**
646
- * Fetch the selectable values for a dashboard parameter, through the chain-filter value endpoint.
647
- */
648
- async function parameterValues(dashboardId, parameterId, options = {}) {
649
- return transport.requestParsed(ParameterValues, `/api/dashboard/${dashboardId}/params/${encodeURIComponent(parameterId)}/values`, { ...options });
650
- }
651
- /**
652
- * Search a dashboard parameter's selectable values: the server returns only values containing the
653
- * substring, capped at the first 1000 matches.
654
- */
655
- async function searchParameterValues(dashboardId, parameterId, query, options = {}) {
656
- const parameter = encodeURIComponent(parameterId);
657
- return transport.requestParsed(ParameterValues, `/api/dashboard/${dashboardId}/params/${parameter}/search/${encodeURIComponent(query)}`, { ...options });
658
- }
659
- return {
660
- list,
661
- get,
662
- create,
663
- update,
664
- archive,
665
- updateDashcard,
666
- checkCardReferences,
667
- parameterValues,
668
- searchParameterValues
669
- };
670
- }
671
- function collectCardReferences(dashcards) {
672
- if (dashcards === void 0 || dashcards === null) return [];
673
- const references = [];
674
- dashcards.forEach((dashcard, index) => {
675
- const parsed = PreflightDashcard.safeParse(dashcard);
676
- if (!parsed.success) return;
677
- const cardId = parsed.data.card_id;
678
- if (typeof cardId === "number" && cardId > 0) references.push({
679
- cardId,
680
- path: `/dashcards/${index}/card_id`
681
- });
682
- });
683
- return references;
684
- }
685
- function groupByCardId(references) {
686
- const grouped = /* @__PURE__ */ new Map();
687
- for (const reference of references) {
688
- const existing = grouped.get(reference.cardId);
689
- if (existing === void 0) grouped.set(reference.cardId, [reference]);
690
- else existing.push(reference);
691
- }
692
- return grouped;
693
- }
694
- function stripEntityId(dashcard) {
695
- const { entity_id: _entity_id, id, size_x, size_y, row, col, ...rest } = dashcard;
696
- return {
697
- ...rest,
698
- id,
699
- size_x,
700
- size_y,
701
- row,
702
- col
703
- };
704
- }
705
- //#endregion
706
- //#region ../client/src/resources/database.ts
707
- const DatabaseApiList = z.object({
708
- data: z.array(Database),
709
- total: z.number().int().nonnegative()
710
- }).loose();
711
- const DatabaseTaskAck = z.object({ status: z.literal("ok") });
712
- const DatabaseApiSchemaList = z.array(z.string());
713
- const DatabaseApiSchemaTableList = z.array(Table);
714
- const SYNC_COMPLETE = "complete";
715
- function databaseResource(transport) {
716
- /** List databases. `include` hydrates each database's tables; `saved` adds the Saved Questions virtual database. */
717
- async function list(params = {}, options = {}) {
718
- const response = await transport.requestParsed(DatabaseApiList, "/api/database", {
719
- ...options,
720
- query: {
721
- include: params.include,
722
- saved: params.saved
723
- }
724
- });
725
- return {
726
- data: response.data,
727
- total: response.total
728
- };
729
- }
730
- /** Get one database by id. `include` hydrates its tables, and `tables.fields` their fields too. */
731
- async function get(id, params = {}, options = {}) {
732
- return transport.requestParsed(Database, `/api/database/${id}`, {
733
- ...options,
734
- query: { include: params.include }
735
- });
736
- }
737
- /** List the schema names in a database. */
738
- async function schemas(id, options = {}) {
739
- return {
740
- data: await transport.requestParsed(DatabaseApiSchemaList, `/api/database/${id}/schemas`, { ...options }),
741
- total: null
742
- };
743
- }
744
- /** List the tables one schema of a database holds. */
745
- async function schemaTables(id, schema, options = {}) {
746
- return {
747
- data: await transport.requestParsed(DatabaseApiSchemaTableList, `/api/database/${id}/schema/${encodeURIComponent(schema)}`, { ...options }),
748
- total: null
749
- };
750
- }
751
- /**
752
- * Trigger a manual schema sync for a database. The endpoint queues the sync and returns at once;
753
- * pass `wait` to poll the database until it reports its initial sync complete.
754
- */
755
- async function syncSchema(id, params = {}, options = {}) {
756
- const ack = await transport.requestParsed(DatabaseTaskAck, `/api/database/${id}/sync_schema`, {
757
- ...options,
758
- method: "POST"
759
- });
760
- const wait = params.wait;
761
- if (wait === void 0) return {
762
- id,
763
- status: ack.status
764
- };
765
- const database = await pollUntil(async (signal) => transport.requestParsed(Database, `/api/database/${id}`, {
766
- ...options,
767
- signal
768
- }), (candidate) => candidate.initial_sync_status === SYNC_COMPLETE, wait);
769
- return {
770
- id,
771
- status: ack.status,
772
- initial_sync_status: database.initial_sync_status ?? null
773
- };
774
- }
775
- /** Trigger a rescan of the cached field values across a database. */
776
- async function rescanValues(id, options = {}) {
777
- return {
778
- id,
779
- status: (await transport.requestParsed(DatabaseTaskAck, `/api/database/${id}/rescan_values`, {
780
- ...options,
781
- method: "POST"
782
- })).status
783
- };
784
- }
785
- return {
786
- list,
787
- get,
788
- schemas,
789
- schemaTables,
790
- syncSchema,
791
- rescanValues
792
- };
793
- }
794
- //#endregion
795
- //#region ../client/src/resources/dataset.ts
796
- function datasetResource(transport) {
797
- /**
798
- * Run an ad-hoc query and return its result envelope. The body is a whole query — MBQL 5, legacy
799
- * MBQL, or native — rather than a reference to a saved one, so nothing here is a card.
800
- */
801
- async function query(body, options = {}) {
802
- return transport.requestParsed(CardQueryResult, "/api/dataset", {
803
- ...options,
804
- method: "POST",
805
- body
806
- });
807
- }
808
- return { query };
809
- }
810
- //#endregion
811
- //#region ../client/src/resources/document.ts
812
- const DocumentApiList = z.object({ items: z.array(Document) }).loose();
813
- function documentResource(transport) {
814
- /** Get existing documents. */
815
- async function list(options = {}) {
816
- return {
817
- data: (await transport.requestParsed(DocumentApiList, "/api/document", { ...options })).items,
818
- total: null
819
- };
820
- }
821
- /** Return an existing document by id. */
822
- async function get(id, options = {}) {
823
- return transport.requestParsed(Document, `/api/document/${id}`, { ...options });
824
- }
825
- /** Create a new document. */
826
- async function create(params, options = {}) {
827
- return transport.requestParsed(Document, "/api/document", {
828
- ...options,
829
- method: "POST",
830
- body: params
831
- });
832
- }
833
- /** Update an existing document by id. */
834
- async function update(id, params, options = {}) {
835
- return transport.requestParsed(Document, `/api/document/${id}`, {
836
- ...options,
837
- method: "PUT",
838
- body: params
839
- });
840
- }
841
- /** Archive (soft-delete) a document by id. Metabase models this as an update, not its own endpoint. */
842
- async function archive(id, options = {}) {
843
- return update(id, { archived: true }, options);
844
- }
845
- return {
846
- list,
847
- get,
848
- create,
849
- update,
850
- archive
851
- };
852
- }
853
- //#endregion
854
- //#region ../client/src/resources/eid-translation.ts
855
- function eidTranslationResource(transport) {
856
- /**
857
- * Translate entity ids to the numeric ids of the rows they name. The request groups the entity
858
- * ids by model; the response is keyed by entity id, each entry carrying its model and — when the
859
- * lookup succeeded — the numeric id.
860
- */
861
- async function translate(params, options = {}) {
862
- return transport.requestParsed(EidTranslateResult, "/api/eid-translation/translate", {
863
- ...options,
864
- method: "POST",
865
- body: params
866
- });
867
- }
868
- return { translate };
869
- }
870
- //#endregion
871
- //#region ../client/src/resources/field.ts
872
- const FieldApiSummary = z.tuple([z.tuple([z.literal("count"), z.number().int()]), z.tuple([z.literal("distincts"), z.number().int()])]);
873
- function fieldResource(transport) {
874
- /** Get one field by id. */
875
- async function get(id, options = {}) {
876
- return transport.requestParsed(Field, `/api/field/${id}`, { ...options });
877
- }
878
- /** Update a field by id, patching only the fields the body carries. */
879
- async function update(id, params, options = {}) {
880
- return transport.requestParsed(Field, `/api/field/${id}`, {
881
- ...options,
882
- method: "PUT",
883
- body: params
884
- });
885
- }
886
- /** Get the row count and the distinct-value count for a field. */
887
- async function summary(id, options = {}) {
888
- const [[, count], [, distincts]] = await transport.requestParsed(FieldApiSummary, `/api/field/${id}/summary`, { ...options });
889
- return {
890
- field_id: id,
891
- count,
892
- distincts
893
- };
894
- }
895
- /** Get the cached distinct values Metabase holds for a field. */
896
- async function values(id, options = {}) {
897
- return transport.requestParsed(FieldValues, `/api/field/${id}/values`, { ...options });
898
- }
899
- return {
900
- get,
901
- update,
902
- summary,
903
- values
904
- };
905
- }
906
- //#endregion
907
- //#region ../client/src/resources/optional-parsed.ts
908
- const NO_CONTENT_STATUS = 204;
909
- async function fetchOptionalParsed(client, path, schema, options = {}) {
910
- const response = await client.requestRaw(path, {
911
- ...options,
912
- method: "GET",
913
- expectContentType: "binary"
914
- });
915
- if (response.status === NO_CONTENT_STATUS) return null;
916
- return parseJsonOrPlain(await response.text(), response.headers.get("content-type"), schema, { source: response.url });
917
- }
918
- //#endregion
919
- //#region ../client/src/resources/git-sync.ts
920
- const SyncScopeCollection = Collection.pick({
921
- id: true,
922
- name: true,
923
- is_remote_synced: true
924
- }).strip();
925
- const SyncDirtyFlag = z.object({ is_dirty: z.boolean() });
926
- const SyncDirtyList = z.object({ dirty: z.array(SyncDirtyItem) });
927
- const SyncBranchList = z.object({ items: z.array(z.string()) });
928
- const SyncImportStarted = z.object({
929
- status: z.literal("success"),
930
- task_id: z.number().int().positive().nullable(),
931
- message: z.string().nullable().optional()
932
- });
933
- const SyncExportStarted = z.object({
934
- message: z.string(),
935
- task_id: z.number().int().positive()
936
- });
937
- const SyncStashStarted = z.object({
938
- status: z.literal("success"),
939
- message: z.string(),
940
- task_id: z.number().int().positive()
941
- });
942
- const RemoteSyncSetting = z.string().nullable();
943
- const FORBIDDEN_STATUS = 403;
944
- const UNREGISTERED_STATUS = 404;
945
- function isRemoteUnreadable(error) {
946
- if (!(error instanceof HttpError)) return false;
947
- return error.status === FORBIDDEN_STATUS || error.status === UNREGISTERED_STATUS;
948
- }
949
- function gitSyncResource(transport) {
950
- /** Get the running or most recently finished sync task, or null when the server has none. */
951
- async function currentTask(options = {}) {
952
- return fetchOptionalParsed(transport, "/api/ee/remote-sync/current-task", SyncTask, options);
953
- }
954
- /** Request cancellation of the running sync task, and answer it in the state that left it. */
955
- async function cancelTask(options = {}) {
956
- return transport.requestParsed(SyncTask, "/api/ee/remote-sync/current-task/cancel", {
957
- ...options,
958
- method: "POST"
959
- });
960
- }
961
- /** Whether Metabase holds content changes the remote has not been told about. */
962
- async function isDirty(options = {}) {
963
- return (await transport.requestParsed(SyncDirtyFlag, "/api/ee/remote-sync/is-dirty", { ...options })).is_dirty;
964
- }
965
- /** List the objects whose local state differs from the remote. */
966
- async function dirty(options = {}) {
967
- return {
968
- data: (await transport.requestParsed(SyncDirtyList, "/api/ee/remote-sync/dirty", { ...options })).dirty,
969
- total: null
970
- };
971
- }
972
- /**
973
- * Compare the tracked remote branch against what Metabase last imported. The server caches the
974
- * comparison; `force-refresh` re-reads the remote instead.
975
- */
976
- async function hasRemoteChanges(params = {}, options = {}) {
977
- return transport.requestParsed(SyncRemoteChanges, "/api/ee/remote-sync/has-remote-changes", {
978
- ...options,
979
- query: { "force-refresh": params["force-refresh"] }
980
- });
981
- }
982
- /**
983
- * Import content from the remote into Metabase. The endpoint queues a task and returns at once;
984
- * pass `wait` to poll that task until it reaches a terminal status. A server already up to date
985
- * answers no task id, and there is then nothing to poll.
986
- */
987
- async function importFromRemote(params = {}, options = {}) {
988
- const started = await transport.requestParsed(SyncImportStarted, "/api/ee/remote-sync/import", {
989
- ...options,
990
- method: "POST",
991
- body: {
992
- branch: params.branch,
993
- force: params.force
994
- }
995
- });
996
- const message = started.message ?? null;
997
- if (params.wait === void 0 || started.task_id === null) return {
998
- message,
999
- task_id: started.task_id
1000
- };
1001
- return {
1002
- message,
1003
- task_id: started.task_id,
1004
- final: await settle(params.wait, options)
1005
- };
1006
- }
1007
- /**
1008
- * Export Metabase's content to the remote. The endpoint queues a task and returns at once; pass
1009
- * `wait` to poll that task until it reaches a terminal status.
1010
- */
1011
- async function exportToRemote(params = {}, options = {}) {
1012
- const started = await transport.requestParsed(SyncExportStarted, "/api/ee/remote-sync/export", {
1013
- ...options,
1014
- method: "POST",
1015
- body: {
1016
- branch: params.branch,
1017
- message: params.message,
1018
- force: params.force
1019
- }
1020
- });
1021
- if (params.wait === void 0) return {
1022
- message: started.message,
1023
- task_id: started.task_id
1024
- };
1025
- return {
1026
- message: started.message,
1027
- task_id: started.task_id,
1028
- final: await settle(params.wait, options)
1029
- };
1030
- }
1031
- /**
1032
- * Export Metabase's current content to a branch the remote does not have yet. The endpoint
1033
- * queues a task and returns at once; pass `wait` to poll that task to a terminal status.
1034
- */
1035
- async function stash(params, options = {}) {
1036
- const started = await transport.requestParsed(SyncStashStarted, "/api/ee/remote-sync/stash", {
1037
- ...options,
1038
- method: "POST",
1039
- body: {
1040
- new_branch: params.new_branch,
1041
- message: params.message
1042
- }
1043
- });
1044
- if (params.wait === void 0) return {
1045
- status: started.status,
1046
- message: started.message,
1047
- task_id: started.task_id
1048
- };
1049
- return {
1050
- status: started.status,
1051
- message: started.message,
1052
- task_id: started.task_id,
1053
- final: await settle(params.wait, options)
1054
- };
1055
- }
1056
- /** List the branches the configured remote carries. */
1057
- async function branches(options = {}) {
1058
- return {
1059
- data: (await transport.requestParsed(SyncBranchList, "/api/ee/remote-sync/branches", { ...options })).items,
1060
- total: null
1061
- };
1062
- }
1063
- /** Create a branch on the remote and point git-sync at it. */
1064
- async function createBranch(params, options = {}) {
1065
- return transport.requestParsed(SyncBranchCreated, "/api/ee/remote-sync/create-branch", {
1066
- ...options,
1067
- method: "POST",
1068
- body: { name: params.name }
1069
- });
1070
- }
1071
- /**
1072
- * Mark one collection as git-synced, or unmark it. The server cascades the flag to descendants
1073
- * by location prefix, and may queue an export task to carry the change to the remote.
1074
- */
1075
- async function setCollectionSynced(collectionId, synced, options = {}) {
1076
- return transport.requestParsed(SyncSettingsUpdateResult, "/api/ee/remote-sync/settings", {
1077
- ...options,
1078
- method: "PUT",
1079
- body: { collections: { [collectionId]: synced } }
1080
- });
1081
- }
1082
- /** The collections currently in git-sync's scope. */
1083
- async function syncedCollections(options = {}) {
1084
- return {
1085
- data: (await listCollectionsWithLibrary(transport, SyncScopeCollection, options)).filter((entry) => entry.is_remote_synced === true),
1086
- total: null
1087
- };
1088
- }
1089
- /** The remote's URL, or null when none is configured or the caller may not read it. */
1090
- async function remoteUrl(options = {}) {
1091
- try {
1092
- const url = await fetchOptionalParsed(transport, "/api/setting/remote-sync-url", RemoteSyncSetting, options);
1093
- return url === "" ? null : url;
1094
- } catch (error) {
1095
- if (isRemoteUnreadable(error)) return null;
1096
- throw error;
1097
- }
1098
- }
1099
- /** The branch git-sync tracks, or null when none is configured or the caller may not read it. */
1100
- async function branch(options = {}) {
1101
- return fetchOptionalParsed(transport, "/api/setting/remote-sync-branch", RemoteSyncSetting, options);
1102
- }
1103
- /**
1104
- * Poll the current task until it reaches a terminal status. A server with no task at all
1105
- * answers null, which is terminal in the same sense: nothing further will happen.
1106
- */
1107
- async function waitForTask(wait, options = {}) {
1108
- return settle(wait, options);
1109
- }
1110
- async function settle(wait, options) {
1111
- return pollUntil(async (signal) => currentTask({
1112
- ...options,
1113
- signal
1114
- }), (task) => task === null || isSyncTaskTerminal(task.status), wait);
1115
- }
1116
- return {
1117
- currentTask,
1118
- cancelTask,
1119
- isDirty,
1120
- dirty,
1121
- hasRemoteChanges,
1122
- import: importFromRemote,
1123
- export: exportToRemote,
1124
- stash,
1125
- branches,
1126
- createBranch,
1127
- setCollectionSynced,
1128
- syncedCollections,
1129
- remoteUrl,
1130
- branch,
1131
- waitForTask
1132
- };
1133
- }
1134
- //#endregion
1135
- //#region ../client/src/resources/library.ts
1136
- const LIBRARY_ROOT_PATH = "/api/ee/library/";
1137
- const PUBLISH_TABLES_PATH = "/api/ee/data-studio/table/publish-tables";
1138
- const UNPUBLISH_TABLES_PATH = "/api/ee/data-studio/table/unpublish-tables";
1139
- const LIBRARY_DATA_TYPE = "library-data";
1140
- const AbsentLibrary = z.object({ data: z.null() });
1141
- const LibraryOrAbsent = z.union([Library, AbsentLibrary]);
1142
- const PublishTablesResponse = z.object({ target_collection: Collection.nullable() });
1143
- const LibraryCollectionInfo = Collection.pick({
1144
- id: true,
1145
- type: true,
1146
- is_remote_synced: true
1147
- }).strip();
1148
- function libraryResource(transport) {
1149
- /** Get the Library root and its child collections, or `null` on an instance that has none. */
1150
- async function get(options = {}) {
1151
- const result = await transport.requestParsed(LibraryOrAbsent, LIBRARY_ROOT_PATH, { ...options });
1152
- if (!("effective_children" in result)) return null;
1153
- const infoById = await libraryCollectionsById(options);
1154
- const effective_children = result.effective_children.map((child) => {
1155
- if (typeof child.id !== "number") return child;
1156
- const info = infoById.get(child.id);
1157
- if (info === void 0) return child;
1158
- return {
1159
- ...child,
1160
- type: info.type ?? child.type,
1161
- is_remote_synced: info.is_remote_synced ?? child.is_remote_synced
1162
- };
1163
- });
1164
- return {
1165
- ...result,
1166
- effective_children
1167
- };
1168
- }
1169
- async function libraryCollectionsById(options) {
1170
- const data = await listCollectionsWithLibrary(transport, LibraryCollectionInfo, options);
1171
- const byId = /* @__PURE__ */ new Map();
1172
- for (const collection of data) if (typeof collection.id === "number") byId.set(collection.id, collection);
1173
- return byId;
1174
- }
1175
- /**
1176
- * Create the Library subtree (its Data and Metrics collections). Metabase takes no body, rejects
1177
- * a second create with a 400, and answers the bare root collection without its
1178
- * `effective_children` — so an existing Library short-circuits the call and a fresh one comes
1179
- * back from a refetch, which together make this idempotent.
1180
- */
1181
- async function create(options = {}) {
1182
- const existing = await get(options);
1183
- if (existing !== null) return existing;
1184
- await transport.requestRaw(LIBRARY_ROOT_PATH, {
1185
- ...options,
1186
- method: "POST"
1187
- });
1188
- const created = await get(options);
1189
- if (created === null) throw new Error(`Library was not created after POST ${LIBRARY_ROOT_PATH}`);
1190
- return created;
1191
- }
1192
- /** The id of the Library's Data collection, creating the Library first when it does not exist. */
1193
- async function ensureDataCollectionId(options = {}) {
1194
- const data = (await create(options)).effective_children.find((child) => child.type === LIBRARY_DATA_TYPE);
1195
- if (data === void 0) throw new Error("Library has no Data collection to publish into");
1196
- if (typeof data.id !== "number") throw new Error(`Library Data collection has a non-numeric id ${String(data.id)}`);
1197
- return data.id;
1198
- }
1199
- /**
1200
- * Publish tables — and every upstream table they depend on — into a collection, so they lead the
1201
- * data pickers and rank up in search. Answers the collection they landed in.
1202
- */
1203
- async function publishTables(params, options = {}) {
1204
- return (await transport.requestParsed(PublishTablesResponse, PUBLISH_TABLES_PATH, {
1205
- ...options,
1206
- method: "POST",
1207
- body: params
1208
- })).target_collection;
1209
- }
1210
- /**
1211
- * Clear the Library collection from tables, and recursively from every downstream table that
1212
- * depends on them. The endpoint answers no JSON body.
1213
- */
1214
- async function unpublishTables(params, options = {}) {
1215
- await transport.requestRaw(UNPUBLISH_TABLES_PATH, {
1216
- ...options,
1217
- method: "POST",
1218
- body: params,
1219
- expectContentType: "binary"
1220
- });
1221
- }
1222
- return {
1223
- get,
1224
- create,
1225
- ensureDataCollectionId,
1226
- publishTables,
1227
- unpublishTables
1228
- };
1229
- }
1230
- //#endregion
1231
- //#region ../client/src/resources/measure.ts
1232
- const MeasureApiList = z.array(Measure);
1233
- function measureResource(transport) {
1234
- /** List measures. */
1235
- async function list(options = {}) {
1236
- return {
1237
- data: await transport.requestParsed(MeasureApiList, "/api/measure", { ...options }),
1238
- total: null
1239
- };
1240
- }
1241
- /** Get one measure by id. */
1242
- async function get(id, options = {}) {
1243
- return transport.requestParsed(Measure, `/api/measure/${id}`, { ...options });
1244
- }
1245
- /** Create a measure — a saved aggregation tied to a table — from a full measure body. */
1246
- async function create(params, options = {}) {
1247
- return transport.requestParsed(Measure, "/api/measure", {
1248
- ...options,
1249
- method: "POST",
1250
- body: params
1251
- });
1252
- }
1253
- /**
1254
- * Update a measure by id, patching only the fields the body carries. `revision_message` is
1255
- * required and lands in the audit log.
1256
- */
1257
- async function update(id, params, options = {}) {
1258
- return transport.requestParsed(Measure, `/api/measure/${id}`, {
1259
- ...options,
1260
- method: "PUT",
1261
- body: params
1262
- });
1263
- }
1264
- /**
1265
- * Archive (soft-delete) a measure by id. Metabase models this as an update, not its own endpoint,
1266
- * so it carries the same required `revision_message`.
1267
- */
1268
- async function archive(id, params, options = {}) {
1269
- return update(id, {
1270
- archived: true,
1271
- revision_message: params.revision_message
1272
- }, options);
1273
- }
1274
- return {
1275
- list,
1276
- get,
1277
- create,
1278
- update,
1279
- archive
1280
- };
1281
- }
1282
- //#endregion
1283
- //#region ../client/src/resources/notification.ts
1284
- const NotificationApiList = z.array(Notification);
1285
- function assertCardAlert(notification) {
1286
- if (notification.payload_type !== "notification/card") throw new ConfigError(`notification ${notification.id} is a ${notification.payload_type}, not a question alert — this operation accepts card alerts only`);
1287
- return notification;
1288
- }
1289
- function mergeAlertUpdate(current, patch) {
1290
- return Notification.parse({
1291
- ...current,
1292
- ...patch,
1293
- id: current.id,
1294
- payload: patch.payload === void 0 ? current.payload : mergePayload(current, patch.payload)
1295
- });
1296
- }
1297
- function mergePayload(current, patch) {
1298
- if (current.payload === null) throw new ConfigError(`alert ${current.id} has lost its card payload — it can be archived, but not patched`);
1299
- return NotificationCardPayload.parse({
1300
- ...current.payload,
1301
- ...patch
1302
- });
1303
- }
1304
- function notificationResource(transport) {
1305
- /**
1306
- * List question alerts, optionally narrowed by the card they watch, their creator, or a
1307
- * recipient. `/api/notification` also serves Metabase's internal system-event notifications, so
1308
- * the request pins the card payload type.
1309
- */
1310
- async function list(params = {}, options = {}) {
1311
- return {
1312
- data: await transport.requestParsed(NotificationApiList, "/api/notification", {
1313
- ...options,
1314
- query: {
1315
- payload_type: CARD_PAYLOAD_TYPE,
1316
- card_id: params.card_id,
1317
- creator_id: params.creator_id,
1318
- recipient_id: params.recipient_id,
1319
- include_inactive: params.include_inactive
1320
- }
1321
- }),
1322
- total: null
1323
- };
1324
- }
1325
- /** Get one question alert by id, refusing an id that names a system-event notification. */
1326
- async function get(id, options = {}) {
1327
- return assertCardAlert(await transport.requestParsed(Notification, `/api/notification/${id}`, { ...options }));
1328
- }
1329
- /** Create a question alert — its card payload, schedules and handlers — from a full body. */
1330
- async function create(params, options = {}) {
1331
- return transport.requestParsed(Notification, "/api/notification", {
1332
- ...options,
1333
- method: "POST",
1334
- body: params
1335
- });
1336
- }
1337
- /** Update a question alert by id, merging the patch over the stored notification. */
1338
- async function update(id, params, options = {}) {
1339
- const current = await get(id, options);
1340
- return transport.requestParsed(Notification, `/api/notification/${id}`, {
1341
- ...options,
1342
- method: "PUT",
1343
- body: mergeAlertUpdate(current, params)
1344
- });
1345
- }
1346
- /** Archive a question alert by id, stopping every delivery. Metabase models this as an update. */
1347
- async function archive(id, options = {}) {
1348
- return update(id, { active: false }, options);
1349
- }
1350
- /**
1351
- * Send a question alert now, off-schedule, to every handler on it. The server answers with no
1352
- * body.
1353
- */
1354
- async function send(id, options = {}) {
1355
- await get(id, options);
1356
- await transport.requestRaw(`/api/notification/${id}/send`, {
1357
- ...options,
1358
- method: "POST",
1359
- expectContentType: "binary"
1360
- });
1361
- }
1362
- return {
1363
- list,
1364
- get,
1365
- create,
1366
- update,
1367
- archive,
1368
- send
1369
- };
1370
- }
1371
- //#endregion
1372
- //#region ../client/src/resources/pulse.ts
1373
- const PulseApiList = z.array(Pulse);
1374
- function mergePulseUpdate(current, patch) {
1375
- return {
1376
- ...patch,
1377
- archived: patch.archived ?? current.archived,
1378
- skip_if_empty: patch.skip_if_empty ?? current.skip_if_empty
1379
- };
1380
- }
1381
- function pulseResource(transport) {
1382
- /** List dashboard subscriptions, optionally narrowed to one dashboard or to the archived ones. */
1383
- async function list(params = {}, options = {}) {
1384
- return {
1385
- data: await transport.requestParsed(PulseApiList, "/api/pulse", {
1386
- ...options,
1387
- query: {
1388
- dashboard_id: params.dashboard_id,
1389
- archived: params.archived
1390
- }
1391
- }),
1392
- total: null
1393
- };
1394
- }
1395
- /** Get one dashboard subscription by id. */
1396
- async function get(id, options = {}) {
1397
- return transport.requestParsed(Pulse, `/api/pulse/${id}`, { ...options });
1398
- }
1399
- /** Create a dashboard subscription — its cards and its delivery channels — from a full body. */
1400
- async function create(params, options = {}) {
1401
- return transport.requestParsed(Pulse, "/api/pulse", {
1402
- ...options,
1403
- method: "POST",
1404
- body: params
1405
- });
1406
- }
1407
- /** Update a dashboard subscription by id, carrying the server-defaulted flags forward. */
1408
- async function update(id, params, options = {}) {
1409
- const current = await get(id, options);
1410
- return transport.requestParsed(Pulse, `/api/pulse/${id}`, {
1411
- ...options,
1412
- method: "PUT",
1413
- body: mergePulseUpdate(current, params)
1414
- });
1415
- }
1416
- /**
1417
- * Archive a dashboard subscription by id, stopping every delivery. Metabase models this as an
1418
- * update, and disables each of the subscription's channels as a side effect.
1419
- */
1420
- async function archive(id, options = {}) {
1421
- return update(id, { archived: true }, options);
1422
- }
1423
- return {
1424
- list,
1425
- get,
1426
- create,
1427
- update,
1428
- archive
1429
- };
1430
- }
1431
- //#endregion
1432
- //#region ../client/src/resources/search.ts
1433
- const SearchApiResponse = z.object({
1434
- data: z.array(SearchResult),
1435
- total: z.number().int().nonnegative()
1436
- }).loose();
1437
- function searchResource(transport) {
1438
- /**
1439
- * Search over the instance's content, ranked against `q`. `models` narrows which kinds of entity
1440
- * may match, `archived` swaps the active set for the archived one, `table_db_id` restricts to
1441
- * items on one database, `verified` to verified content, and `limit`/`offset` are the window the
1442
- * server applies before ranking hydration.
1443
- */
1444
- async function query(params = {}, options = {}) {
1445
- const response = await transport.requestParsed(SearchApiResponse, "/api/search", {
1446
- ...options,
1447
- query: {
1448
- q: params.q,
1449
- models: params.models,
1450
- archived: params.archived,
1451
- limit: params.limit,
1452
- offset: params.offset,
1453
- table_db_id: params.table_db_id,
1454
- verified: params.verified
1455
- }
1456
- });
1457
- return {
1458
- data: response.data,
1459
- total: response.total
1460
- };
1461
- }
1462
- return { query };
1463
- }
1464
- //#endregion
1465
- //#region ../client/src/resources/segment.ts
1466
- const SegmentApiList = z.array(Segment);
1467
- function segmentResource(transport) {
1468
- /** List every segment the caller can see. */
1469
- async function list(options = {}) {
1470
- return {
1471
- data: await transport.requestParsed(SegmentApiList, "/api/segment", { ...options }),
1472
- total: null
1473
- };
1474
- }
1475
- /** Get one segment by id. */
1476
- async function get(id, options = {}) {
1477
- return transport.requestParsed(Segment, `/api/segment/${id}`, { ...options });
1478
- }
1479
- /** Create a segment — a reusable row filter over one table — from a full segment body. */
1480
- async function create(params, options = {}) {
1481
- return transport.requestParsed(Segment, "/api/segment", {
1482
- ...options,
1483
- method: "POST",
1484
- body: params
1485
- });
1486
- }
1487
- /**
1488
- * Update a segment by id, patching only the fields the body carries. `revision_message` is
1489
- * required: Metabase records every segment change in its revision history.
1490
- */
1491
- async function update(id, params, options = {}) {
1492
- return transport.requestParsed(Segment, `/api/segment/${id}`, {
1493
- ...options,
1494
- method: "PUT",
1495
- body: params
1496
- });
1497
- }
1498
- /**
1499
- * Archive (soft-delete) a segment by id. Metabase models this as an update, so it carries the
1500
- * same required `revision_message`.
1501
- */
1502
- async function archive(id, params, options = {}) {
1503
- return update(id, {
1504
- archived: true,
1505
- revision_message: params.revision_message
1506
- }, options);
1507
- }
1508
- return {
1509
- list,
1510
- get,
1511
- create,
1512
- update,
1513
- archive
1514
- };
1515
- }
1516
- //#endregion
1517
- //#region ../client/src/resources/setting.ts
1518
- const SettingApiList = z.array(Setting);
1519
- const UNKNOWN_SETTING_PREFIX = "Unknown setting:";
1520
- function rethrowSettingError(error, key) {
1521
- if (errorMessage(error).startsWith(UNKNOWN_SETTING_PREFIX)) throw new ConfigError(`unknown setting: ${key}`);
1522
- throw error;
1523
- }
1524
- function settingResource(transport) {
1525
- /** Get all settings and their values, with descriptions and environment-variable names. */
1526
- async function list(options = {}) {
1527
- return {
1528
- data: await transport.requestParsed(SettingApiList, "/api/setting", { ...options }),
1529
- total: null
1530
- };
1531
- }
1532
- /**
1533
- * Fetch a single setting's value by key. An unset setting answers 204 rather than 404, which
1534
- * reaches the caller as `null`; older servers answer the value as bare text rather than JSON.
1535
- */
1536
- async function get(key, options = {}) {
1537
- return fetchOptionalParsed(transport, `/api/setting/${encodeURIComponent(key)}`, z.unknown(), options).catch((error) => rethrowSettingError(error, key));
1538
- }
1539
- /** Set a single setting's value by key. The endpoint answers 204 with no body. */
1540
- async function set(key, value, options = {}) {
1541
- await transport.requestRaw(`/api/setting/${encodeURIComponent(key)}`, {
1542
- ...options,
1543
- method: "PUT",
1544
- body: { value },
1545
- expectContentType: "binary"
1546
- }).catch((error) => rethrowSettingError(error, key));
1547
- }
1548
- return {
1549
- list,
1550
- get,
1551
- set
1552
- };
1553
- }
1554
- //#endregion
1555
- //#region ../client/src/resources/setup.ts
1556
- function setupResource(transport) {
1557
- /**
1558
- * Complete the initial setup wizard on a fresh instance, creating its first admin user and
1559
- * applying the instance preferences. The setup token is single-use.
1560
- */
1561
- async function create(params, options = {}) {
1562
- return transport.requestParsed(SetupResult, "/api/setup", {
1563
- ...options,
1564
- method: "POST",
1565
- body: params
1566
- });
1567
- }
1568
- return { create };
1569
- }
1570
- //#endregion
1571
- //#region ../client/src/resources/snippet.ts
1572
- const SnippetApiList = z.array(Snippet);
1573
- function snippetResource(transport) {
1574
- /** List native query snippets. `archived` swaps the listing to archived snippets. */
1575
- async function list(params = {}, options = {}) {
1576
- return {
1577
- data: await transport.requestParsed(SnippetApiList, "/api/native-query-snippet", {
1578
- ...options,
1579
- query: { archived: params.archived }
1580
- }),
1581
- total: null
1582
- };
1583
- }
1584
- /** Get one native query snippet by id. */
1585
- async function get(id, options = {}) {
1586
- return transport.requestParsed(Snippet, `/api/native-query-snippet/${id}`, { ...options });
1587
- }
1588
- /** Create a native query snippet from a name, its SQL fragment, and an optional collection. */
1589
- async function create(params, options = {}) {
1590
- return transport.requestParsed(Snippet, "/api/native-query-snippet", {
1591
- ...options,
1592
- method: "POST",
1593
- body: params
1594
- });
1595
- }
1596
- /** Update a native query snippet by id, patching only the fields the body carries. */
1597
- async function update(id, params, options = {}) {
1598
- return transport.requestParsed(Snippet, `/api/native-query-snippet/${id}`, {
1599
- ...options,
1600
- method: "PUT",
1601
- body: params
1602
- });
1603
- }
1604
- /**
1605
- * Archive (soft-delete) a native query snippet by id. Metabase models this as an update, not its
1606
- * own endpoint.
1607
- */
1608
- async function archive(id, options = {}) {
1609
- return update(id, { archived: true }, options);
1610
- }
1611
- return {
1612
- list,
1613
- get,
1614
- create,
1615
- update,
1616
- archive
1617
- };
1618
- }
1619
- //#endregion
1620
- //#region ../client/src/resources/csv-upload.ts
1621
- const CSV_CONTENT_TYPE = "text/csv";
1622
- function buildCsvFormData(file) {
1623
- const form = new FormData();
1624
- form.append("file", new Blob([file.bytes], { type: CSV_CONTENT_TYPE }), file.filename);
1625
- return form;
1626
- }
1627
- //#endregion
1628
- //#region ../client/src/resources/table.ts
1629
- const TableApiList = z.array(Table);
1630
- const UPLOAD_UPDATE_PATHS = {
1631
- append: "append-csv",
1632
- replace: "replace-csv"
1633
- };
1634
- function tableResource(transport) {
1635
- /** List every table the caller can see, across all databases. */
1636
- async function list(options = {}) {
1637
- return {
1638
- data: await transport.requestParsed(TableApiList, "/api/table", { ...options }),
1639
- total: null
1640
- };
1641
- }
1642
- /** Get one table by id, without its fields. */
1643
- async function get(id, options = {}) {
1644
- return transport.requestParsed(Table, `/api/table/${id}`, { ...options });
1645
- }
1646
- /** Update a table by id, patching only the fields the body carries. */
1647
- async function update(id, params, options = {}) {
1648
- return transport.requestParsed(Table, `/api/table/${id}`, {
1649
- ...options,
1650
- method: "PUT",
1651
- body: params
1652
- });
1653
- }
1654
- /** Get a table by id with its fields hydrated — the metadata the query builder runs on. */
1655
- async function queryMetadata(id, options = {}) {
1656
- return transport.requestParsed(TableQueryMetadata, `/api/table/${id}/query_metadata`, { ...options });
1657
- }
1658
- async function updateFromCsv(id, action, file, options) {
1659
- await transport.requestRaw(`/api/table/${id}/${UPLOAD_UPDATE_PATHS[action]}`, {
1660
- ...options,
1661
- method: "POST",
1662
- body: buildCsvFormData(file),
1663
- expectContentType: "binary"
1664
- });
1665
- return {
1666
- table_id: id,
1667
- action
1668
- };
1669
- }
1670
- /**
1671
- * Inserts the rows of an uploaded CSV file into the table identified by `id`. The table must have
1672
- * been created by uploading a CSV file.
1673
- *
1674
- * The file may be at most 50 MB; larger uploads are rejected with a 413 response.
1675
- */
1676
- async function appendCsv(id, file, options = {}) {
1677
- return updateFromCsv(id, "append", file, options);
1678
- }
1679
- /**
1680
- * Replaces the contents of the table identified by `id` with the rows of an uploaded CSV file.
1681
- * The table must have been created by uploading a CSV file.
1682
- *
1683
- * The file may be at most 50 MB; larger uploads are rejected with a 413 response.
1684
- */
1685
- async function replaceCsv(id, file, options = {}) {
1686
- return updateFromCsv(id, "replace", file, options);
1687
- }
1688
- return {
1689
- list,
1690
- get,
1691
- update,
1692
- queryMetadata,
1693
- appendCsv,
1694
- replaceCsv
1695
- };
1696
- }
1697
- //#endregion
1698
- //#region ../client/src/resources/timeline-event.ts
1699
- function timelineEventResource(transport) {
1700
- /** Get one timeline event by id. */
1701
- async function get(id, options = {}) {
1702
- return transport.requestParsed(TimelineEvent, `/api/timeline-event/${id}`, { ...options });
1703
- }
1704
- /** Create a timeline event on an existing timeline. */
1705
- async function create(params, options = {}) {
1706
- return transport.requestParsed(TimelineEvent, "/api/timeline-event", {
1707
- ...options,
1708
- method: "POST",
1709
- body: params
1710
- });
1711
- }
1712
- /**
1713
- * Update a timeline event by id, patching only the fields the body carries. `timeline_id` moves
1714
- * the event to another timeline.
1715
- */
1716
- async function update(id, params, options = {}) {
1717
- return transport.requestParsed(TimelineEvent, `/api/timeline-event/${id}`, {
1718
- ...options,
1719
- method: "PUT",
1720
- body: params
1721
- });
1722
- }
1723
- /**
1724
- * Archive (soft-delete) a timeline event by id. Metabase models this as an update, not its own
1725
- * endpoint.
1726
- */
1727
- async function archive(id, options = {}) {
1728
- return update(id, { archived: true }, options);
1729
- }
1730
- /** Permanently delete a timeline event by id. The server answers with no body. */
1731
- async function remove(id, options = {}) {
1732
- await transport.requestRaw(`/api/timeline-event/${id}`, {
1733
- ...options,
1734
- method: "DELETE",
1735
- expectContentType: "binary"
1736
- });
1737
- }
1738
- return {
1739
- get,
1740
- create,
1741
- update,
1742
- archive,
1743
- delete: remove
1744
- };
1745
- }
1746
- //#endregion
1747
- //#region ../client/src/resources/timeline.ts
1748
- const TimelineApiList = z.array(Timeline);
1749
- const TimelineWithEvents = Timeline.required({ events: true });
1750
- function timelineResource(transport) {
1751
- /** List timelines. `archived` swaps the active listing for the archived one. */
1752
- async function list(params = {}, options = {}) {
1753
- return {
1754
- data: await transport.requestParsed(TimelineApiList, "/api/timeline", {
1755
- ...options,
1756
- query: { archived: params.archived }
1757
- }),
1758
- total: null
1759
- };
1760
- }
1761
- /** Get one timeline by id, without its events. */
1762
- async function get(id, options = {}) {
1763
- return transport.requestParsed(Timeline, `/api/timeline/${id}`, { ...options });
1764
- }
1765
- /**
1766
- * List the events on one timeline. Metabase has no endpoint of its own for these: the same
1767
- * timeline read hydrates them on request, and `archived` chooses which of them come back.
1768
- */
1769
- async function events(id, params = {}, options = {}) {
1770
- return {
1771
- data: (await transport.requestParsed(TimelineWithEvents, `/api/timeline/${id}`, {
1772
- ...options,
1773
- query: {
1774
- include: "events",
1775
- archived: params.archived
1776
- }
1777
- })).events,
1778
- total: null
1779
- };
1780
- }
1781
- /** Create a timeline from a full timeline body. */
1782
- async function create(params, options = {}) {
1783
- return transport.requestParsed(Timeline, "/api/timeline", {
1784
- ...options,
1785
- method: "POST",
1786
- body: params
1787
- });
1788
- }
1789
- /**
1790
- * Update a timeline by id, patching only the fields the body carries. Changing `archived`
1791
- * cascades to every event on the timeline.
1792
- */
1793
- async function update(id, params, options = {}) {
1794
- return transport.requestParsed(Timeline, `/api/timeline/${id}`, {
1795
- ...options,
1796
- method: "PUT",
1797
- body: params
1798
- });
1799
- }
1800
- /**
1801
- * Archive (soft-delete) a timeline and all its events by id. Metabase models this as an update,
1802
- * not its own endpoint.
1803
- */
1804
- async function archive(id, options = {}) {
1805
- return update(id, { archived: true }, options);
1806
- }
1807
- /** Permanently delete a timeline and all its events by id. The server answers with no body. */
1808
- async function remove(id, options = {}) {
1809
- await transport.requestRaw(`/api/timeline/${id}`, {
1810
- ...options,
1811
- method: "DELETE",
1812
- expectContentType: "binary"
1813
- });
1814
- }
1815
- return {
1816
- list,
1817
- get,
1818
- events,
1819
- create,
1820
- update,
1821
- archive,
1822
- delete: remove
1823
- };
1824
- }
1825
- //#endregion
1826
- //#region ../client/src/resources/transform-job.ts
1827
- const TransformJobApiList = z.array(TransformJob);
1828
- const TransformApiList$1 = z.array(Transform);
1829
- function transformJobResource(transport) {
1830
- /** List every transform job the caller can see. */
1831
- async function list(options = {}) {
1832
- return {
1833
- data: await transport.requestParsed(TransformJobApiList, "/api/transform-job", { ...options }),
1834
- total: null
1835
- };
1836
- }
1837
- /** Get one transform job by id. */
1838
- async function get(id, options = {}) {
1839
- return transport.requestParsed(TransformJob, `/api/transform-job/${id}`, { ...options });
1840
- }
1841
- /** Create a transform job — a schedule plus the tags it runs — from a full body. */
1842
- async function create(params, options = {}) {
1843
- return transport.requestParsed(TransformJob, "/api/transform-job", {
1844
- ...options,
1845
- method: "POST",
1846
- body: params
1847
- });
1848
- }
1849
- /** Update a transform job by id, patching only the fields the body carries. */
1850
- async function update(id, params, options = {}) {
1851
- return transport.requestParsed(TransformJob, `/api/transform-job/${id}`, {
1852
- ...options,
1853
- method: "PUT",
1854
- body: params
1855
- });
1856
- }
1857
- /** Delete a transform job by id, leaving the transforms it ran untouched. */
1858
- async function remove(id, options = {}) {
1859
- await transport.requestRaw(`/api/transform-job/${id}`, {
1860
- ...options,
1861
- method: "DELETE",
1862
- expectContentType: "binary"
1863
- });
1864
- }
1865
- /**
1866
- * Start a run of a transform job by id. The job runs every transform carrying one of its tags,
1867
- * plus those transforms' dependencies; `run_all` re-runs dependencies that are already fresh.
1868
- */
1869
- async function run(id, params = {}, options = {}) {
1870
- return transport.requestParsed(TransformJobRunResult, `/api/transform-job/${id}/run`, {
1871
- ...options,
1872
- method: "POST",
1873
- body: { run_all: params.run_all }
1874
- });
1875
- }
1876
- /** List the transforms a job would execute, resolved from the job's tags. */
1877
- async function transforms(id, options = {}) {
1878
- return {
1879
- data: await transport.requestParsed(TransformApiList$1, `/api/transform-job/${id}/transforms`, { ...options }),
1880
- total: null
1881
- };
1882
- }
1883
- /**
1884
- * Flip the active flag on every transform job at once. Inactive jobs do not run on schedule;
1885
- * manual runs ignore the flag. The path carries no id and is a different endpoint from `update`.
1886
- */
1887
- async function setActive(active, options = {}) {
1888
- return transport.requestParsed(TransformJobActiveResult, "/api/transform-job/active", {
1889
- ...options,
1890
- method: "PUT",
1891
- body: { active }
1892
- });
1893
- }
1894
- return {
1895
- list,
1896
- get,
1897
- create,
1898
- update,
1899
- delete: remove,
1900
- run,
1901
- transforms,
1902
- setActive
1903
- };
1904
- }
1905
- //#endregion
1906
- //#region ../client/src/resources/transform.ts
1907
- const TransformApiList = z.array(Transform);
1908
- const TransformRunKickoff = z.object({
1909
- message: z.string(),
1910
- run_id: z.number().int().positive().nullable()
1911
- });
1912
- function transformResource(transport) {
1913
- /** List every transform the caller can see. */
1914
- async function list(options = {}) {
1915
- return {
1916
- data: await transport.requestParsed(TransformApiList, "/api/transform", { ...options }),
1917
- total: null
1918
- };
1919
- }
1920
- /** Get one transform by id. */
1921
- async function get(id, options = {}) {
1922
- return transport.requestParsed(Transform, `/api/transform/${id}`, { ...options });
1923
- }
1924
- /** Create a transform — a query plus the warehouse table it writes — from a full body. */
1925
- async function create(params, options = {}) {
1926
- return transport.requestParsed(Transform, "/api/transform", {
1927
- ...options,
1928
- method: "POST",
1929
- body: params
1930
- });
1931
- }
1932
- /** Update a transform by id, patching only the fields the body carries. */
1933
- async function update(id, params, options = {}) {
1934
- return transport.requestParsed(Transform, `/api/transform/${id}`, {
1935
- ...options,
1936
- method: "PUT",
1937
- body: params
1938
- });
1939
- }
1940
- /** Delete a transform by id, leaving any table it already materialized in place. */
1941
- async function remove(id, options = {}) {
1942
- await transport.requestRaw(`/api/transform/${id}`, {
1943
- ...options,
1944
- method: "DELETE",
1945
- expectContentType: "binary"
1946
- });
1947
- }
1948
- /** Drop a transform's materialized output table, keeping the transform definition. */
1949
- async function deleteTable(id, options = {}) {
1950
- await transport.requestRaw(`/api/transform/${id}/table`, {
1951
- ...options,
1952
- method: "DELETE",
1953
- expectContentType: "binary"
1954
- });
1955
- }
1956
- /** List the upstream transforms a transform depends on. */
1957
- async function dependencies(id, options = {}) {
1958
- return {
1959
- data: await transport.requestParsed(TransformApiList, `/api/transform/${id}/dependencies`, { ...options }),
1960
- total: null
1961
- };
1962
- }
1963
- /** Request cancellation of a transform's current run. */
1964
- async function cancel(id, options = {}) {
1965
- await transport.requestRaw(`/api/transform/${id}/cancel`, {
1966
- ...options,
1967
- method: "POST",
1968
- expectContentType: "binary"
1969
- });
1970
- }
1971
- /** Get one transform run by run id — not by the id of the transform that produced it. */
1972
- async function getRun(runId, options = {}) {
1973
- return transport.requestParsed(TransformRun, `/api/transform/run/${runId}`, { ...options });
1974
- }
1975
- /** Walk the run history, newest first, optionally narrowed to a single transform. */
1976
- function runPages(params = {}, options = {}) {
1977
- return paginatePages(transport, "/api/transform/run", TransformRun, {
1978
- query: { "transform-ids": params["transform-ids"] },
1979
- ...options.offset !== void 0 && { offset: options.offset },
1980
- ...options.max !== void 0 && { max: options.max },
1981
- ...options.pageSize !== void 0 && { pageSize: options.pageSize },
1982
- ...options.signal !== void 0 && { signal: options.signal }
1983
- });
1984
- }
1985
- /**
1986
- * Start a run of a transform by id. The server queues the run and answers at once; `wait` polls
1987
- * it to a terminal status, and `syncTarget` follows that with the output table's registration.
1988
- * A server that answers no run id started nothing, and there is then nothing to poll.
1989
- */
1990
- async function run(id, params = {}, options = {}) {
1991
- const kickoff = await transport.requestParsed(TransformRunKickoff, `/api/transform/${id}/run`, {
1992
- ...options,
1993
- method: "POST"
1994
- });
1995
- const schedule = params.syncTarget === true ? params.wait ?? {} : params.wait;
1996
- if (schedule === void 0 || kickoff.run_id === null) return {
1997
- message: kickoff.message,
1998
- run_id: kickoff.run_id,
1999
- final: null
2000
- };
2001
- const runId = kickoff.run_id;
2002
- const final = await pollUntil(async (signal) => getRun(runId, {
2003
- ...options,
2004
- signal
2005
- }), (candidate) => isTransformRunTerminal(candidate.status), schedule);
2006
- if (params.syncTarget !== true) return {
2007
- message: kickoff.message,
2008
- run_id: runId,
2009
- final
2010
- };
2011
- const targetTableId = isTransformRunFailed(final.status) ? null : await awaitTargetTableId(id, schedule, options);
2012
- return {
2013
- message: kickoff.message,
2014
- run_id: runId,
2015
- final,
2016
- target_table_id: targetTableId
2017
- };
2018
- }
2019
- async function awaitTargetTableId(id, wait, options) {
2020
- try {
2021
- return linkedTableId(await pollUntil(async (signal) => get(id, {
2022
- ...options,
2023
- signal
2024
- }), (transform) => linkedTableId(transform) !== null, wait));
2025
- } catch (error) {
2026
- if (error instanceof TimeoutError) return null;
2027
- throw error;
2028
- }
2029
- }
2030
- return {
2031
- list,
2032
- get,
2033
- create,
2034
- update,
2035
- delete: remove,
2036
- deleteTable,
2037
- dependencies,
2038
- cancel,
2039
- getRun,
2040
- runPages,
2041
- run
2042
- };
2043
- }
2044
- function linkedTableId(transform) {
2045
- return transform.target_table_id ?? transform.table?.id ?? null;
2046
- }
2047
- //#endregion
2048
- //#region ../client/src/resources/transform-tag.ts
2049
- const TransformTagApiList = z.array(TransformTag);
2050
- function transformTagResource(transport) {
2051
- /** List every transform tag the caller can see, built-in tags included. */
2052
- async function list(options = {}) {
2053
- return {
2054
- data: await transport.requestParsed(TransformTagApiList, "/api/transform-tag", { ...options }),
2055
- total: null
2056
- };
2057
- }
2058
- /** Create a transform tag, the label a transform job matches transforms on. */
2059
- async function create(params, options = {}) {
2060
- return transport.requestParsed(TransformTag, "/api/transform-tag", {
2061
- ...options,
2062
- method: "POST",
2063
- body: params
2064
- });
2065
- }
2066
- /** Rename a transform tag by id. */
2067
- async function update(id, params, options = {}) {
2068
- return transport.requestParsed(TransformTag, `/api/transform-tag/${id}`, {
2069
- ...options,
2070
- method: "PUT",
2071
- body: params
2072
- });
2073
- }
2074
- /** Delete a transform tag by id, detaching it from every transform and job carrying it. */
2075
- async function remove(id, options = {}) {
2076
- await transport.requestRaw(`/api/transform-tag/${id}`, {
2077
- ...options,
2078
- method: "DELETE",
2079
- expectContentType: "binary"
2080
- });
2081
- }
2082
- return {
2083
- list,
2084
- create,
2085
- update,
2086
- delete: remove
2087
- };
2088
- }
2089
- //#endregion
2090
- //#region ../client/src/resources/upload.ts
2091
- const UPLOAD_TABLE_ID_HEADER = "metabase-table-id";
2092
- function uploadResource(transport) {
2093
- /**
2094
- * Create a table and model populated with the values from the attached CSV. Returns the model ID
2095
- * if successful.
2096
- *
2097
- * The file may be at most 50 MB; larger uploads are rejected with a 413 response.
2098
- */
2099
- async function createFromCsv(file, params, options = {}) {
2100
- const form = buildCsvFormData(file);
2101
- form.append("collection_id", params.collection_id);
2102
- const response = await transport.requestRaw("/api/upload/csv", {
2103
- ...options,
2104
- method: "POST",
2105
- body: form,
2106
- expectContentType: "binary"
2107
- });
2108
- return parseCreateUploadResult(await response.text(), response.headers);
2109
- }
2110
- return { createFromCsv };
2111
- }
2112
- function parseCreateUploadResult(bodyText, headers) {
2113
- return UploadResult.parse({
2114
- model_id: parseResponseInteger(bodyText, "response body"),
2115
- table_id: parseResponseInteger(headers.get(UPLOAD_TABLE_ID_HEADER), `${UPLOAD_TABLE_ID_HEADER} header`)
2116
- });
2117
- }
2118
- function parseResponseInteger(value, source) {
2119
- const trimmed = value?.trim() ?? "";
2120
- if (trimmed === "") throw new ResponseShapeError(`upload succeeded but the ${source} was empty`, {
2121
- kind: "decoded",
2122
- source,
2123
- value
2124
- });
2125
- const parsed = Number(trimmed);
2126
- if (!Number.isInteger(parsed)) throw new ResponseShapeError(`upload succeeded but the ${source} was not an integer: ${JSON.stringify(trimmed)}`, {
2127
- kind: "decoded",
2128
- source,
2129
- value
2130
- });
2131
- return parsed;
2132
- }
2133
- //#endregion
2134
- //#region ../client/src/domain/user.ts
2135
- const CurrentUser = z.object({
2136
- id: z.number().int(),
2137
- email: z.email(),
2138
- common_name: z.string(),
2139
- is_superuser: z.boolean()
2140
- }).loose();
2141
- CurrentUser.pick({
2142
- id: true,
2143
- email: true,
2144
- common_name: true,
2145
- is_superuser: true
2146
- }).strip();
2147
- //#endregion
2148
- //#region ../client/src/resources/user.ts
2149
- function userResource(transport) {
2150
- /** Get the user the request's credentials authenticate as. */
2151
- async function current(options = {}) {
2152
- return transport.requestParsed(CurrentUser, "/api/user/current", { ...options });
2153
- }
2154
- return { current };
2155
- }
2156
- //#endregion
2157
- //#region ../client/src/client.ts
2158
- var client_exports = /* @__PURE__ */ __exportAll({ createClient: () => createClient });
2159
- function createClient(config, options) {
2160
- const transport = createTransport(config, options);
2161
- return {
2162
- card: cardResource(transport),
2163
- collection: collectionResource(transport),
2164
- dashboard: dashboardResource(transport),
2165
- database: databaseResource(transport),
2166
- dataset: datasetResource(transport),
2167
- document: documentResource(transport),
2168
- eidTranslation: eidTranslationResource(transport),
2169
- field: fieldResource(transport),
2170
- gitSync: gitSyncResource(transport),
2171
- library: libraryResource(transport),
2172
- measure: measureResource(transport),
2173
- notification: notificationResource(transport),
2174
- pulse: pulseResource(transport),
2175
- search: searchResource(transport),
2176
- segment: segmentResource(transport),
2177
- setting: settingResource(transport),
2178
- setup: setupResource(transport),
2179
- snippet: snippetResource(transport),
2180
- table: tableResource(transport),
2181
- timeline: timelineResource(transport),
2182
- timelineEvent: timelineEventResource(transport),
2183
- transform: transformResource(transport),
2184
- transformJob: transformJobResource(transport),
2185
- transformTag: transformTagResource(transport),
2186
- upload: uploadResource(transport),
2187
- user: userResource(transport),
2188
- requestParsed: transport.requestParsed,
2189
- requestRaw: transport.requestRaw,
2190
- requestStream: transport.requestStream
2191
- };
2192
- }
2193
- //#endregion
2194
- export { createClient as n, client_exports as t };