@metabase/cli 0.3.2 → 0.4.0-alpha.release-65-integration-branch.31ca6bb
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.
- package/dist/{add-collection-BjVAdZ1n.mjs → add-collection-B-Kczwcj.mjs} +5 -5
- package/dist/{alert-DCLhfwdv.mjs → alert-Ne0ivd5m.mjs} +7 -7
- package/dist/{alerts-DRin_wt2.mjs → alerts-Fakzg9iP.mjs} +6 -6
- package/dist/{append-DQ9rPJHZ.mjs → append-DCDVqPmR.mjs} +4 -4
- package/dist/archive-55sDfnHf.mjs +32 -0
- package/dist/{archive-_c-ISZmi.mjs → archive-BNJit8eD.mjs} +3 -3
- package/dist/{archive-o5cWV3vZ.mjs → archive-BbNqts-V.mjs} +3 -3
- package/dist/{archive-D6xzHaM3.mjs → archive-C93UR4Uc.mjs} +3 -3
- package/dist/{archive-BzVxRqpL.mjs → archive-CGmvQht4.mjs} +5 -5
- package/dist/{archive-COFQAHAL.mjs → archive-CL8wqAzm.mjs} +3 -3
- package/dist/{archive-BVRKE9Ev.mjs → archive-CSdktxvW.mjs} +5 -5
- package/dist/{archive-D3yPvUtz.mjs → archive-CpCSY4RT.mjs} +5 -5
- package/dist/{archive-xcgoVPwv.mjs → archive-DCCkQTjQ.mjs} +5 -5
- package/dist/{archive-BPCgmLcV.mjs → archive-DCE087yD.mjs} +4 -4
- package/dist/{archive-1YVo-Wsu.mjs → archive-DEef7eB8.mjs} +3 -3
- package/dist/{archive-HeRygdKz2.mjs → archive-DIZu7o4C.mjs} +4 -4
- package/dist/{auth-DJn5T6zA.mjs → auth-Bx4QQhqt.mjs} +5 -5
- package/dist/body-CB2eDFFb.mjs +17 -0
- package/dist/branch-flag-pFQPNYKr.mjs +9 -0
- package/dist/{branches-CUyPxeeW.mjs → branches-B6ilUG-7.mjs} +3 -3
- package/dist/breaking-Dg3-8yDF.mjs +36 -0
- package/dist/broken-BNBD4Eo3.mjs +37 -0
- package/dist/bulk-discard-values-DfKXuZpR.mjs +49 -0
- package/dist/bulk-edit-oUCfDQ_M.mjs +53 -0
- package/dist/bulk-rescan-values-B8pNlXUH.mjs +28 -0
- package/dist/bulk-sync-schema-tRp7jBJt.mjs +28 -0
- package/dist/{cancel-BNuVls58.mjs → cancel-Bl4BMkwI.mjs} +3 -3
- package/dist/{cancel-task-DUmlQQpi.mjs → cancel-task-CWWo7vLf.mjs} +4 -4
- package/dist/card-CQD4D8mw.mjs +25 -0
- package/dist/{card-CEkp1mcI.mjs → card-CQNUT9pm.mjs} +1 -1
- package/dist/{card-voh1k4hl.mjs → card-P5mBknsl.mjs} +3 -11
- package/dist/{cards-_gbvw3wp.mjs → cards-BIUYdSIR.mjs} +6 -6
- package/dist/cli.mjs +420 -100
- package/dist/{client-BnK0evYf.mjs → client-BHIFvEg2.mjs} +394 -316
- package/dist/{collection-DYM0p3Xl.mjs → collection-BG3Ksea-.mjs} +1 -1
- package/dist/collection-CuaTd10G.mjs +21 -0
- package/dist/{collection-BxdPxD38.mjs → collection-D3KXhvnc.mjs} +7 -5
- package/dist/{collection-namespace-DM90lA8C.mjs → collection-namespace-ZQePD67z.mjs} +2 -2
- package/dist/{content-translation-CqB3peU9.mjs → content-translation-BRdNdAmn.mjs} +3 -3
- package/dist/copy-BMEaYmTb.mjs +55 -0
- package/dist/copy-CbDfVZRC.mjs +36 -0
- package/dist/copy-flags-anRhAvB5.mjs +32 -0
- package/dist/{create-BIUVvIGH.mjs → create-5cDaZcRL.mjs} +3 -3
- package/dist/{create-CwXUMOMd.mjs → create-BEN-2XFK.mjs} +3 -3
- package/dist/create-BJG630xB.mjs +48 -0
- package/dist/{create-IFjwHs0G.mjs → create-BTQB1lqX.mjs} +4 -4
- package/dist/{create-BMKuihoI.mjs → create-C3TmU1Bi.mjs} +6 -6
- package/dist/create-C7O9tPL2.mjs +34 -0
- package/dist/{create-DVo8-IzZ.mjs → create-C8hsOv_D.mjs} +6 -6
- package/dist/{create-DNx9TGHs.mjs → create-CBSsW8Hm.mjs} +6 -6
- package/dist/{create-Cm9Z-rfe2.mjs → create-CG6WWY6k.mjs} +4 -4
- package/dist/{create-BSvTs-EV.mjs → create-D2Shlb7t.mjs} +3 -3
- package/dist/{create-DMVw9nrZ.mjs → create-DVEqry26.mjs} +4 -4
- package/dist/{create-B48rmY8v.mjs → create-D_pNX7d0.mjs} +3 -3
- package/dist/{create-D4Y69cDF.mjs → create-R0Q-nRlq.mjs} +4 -4
- package/dist/{create-CUHpxANR.mjs → create-SqmOf6WQ.mjs} +6 -6
- package/dist/{create-branch-Cw-uXows.mjs → create-branch-Cb3CWojg.mjs} +4 -4
- package/dist/{create-CnJKj9Nl.mjs → create-c2zR9y4J.mjs} +4 -4
- package/dist/{create-va8bByVt.mjs → create-xt4ff6fP.mjs} +3 -3
- package/dist/{create-B7S5fCkD.mjs → create-zpJIRn9j.mjs} +5 -5
- package/dist/{csv-CaKx1oFZ.mjs → csv-CRNOhy4X.mjs} +4 -4
- package/dist/{current-task-lGh69Z1i.mjs → current-task-DFo1ZJ51.mjs} +4 -4
- package/dist/dashboard-D11YAa7I.mjs +35 -0
- package/dist/{dashboard-D0hwTC-f.mjs → dashboard-Phz3XpRM.mjs} +2 -1
- package/dist/{dashboard-DgK81azj.mjs → dashboard-XSTr9QCr.mjs} +6 -2
- package/dist/data-action-BiHjjVjc.mjs +24 -0
- package/dist/data-action-DZxVB_hD.mjs +85 -0
- package/dist/data-action-R9qxJDPA.mjs +40 -0
- package/dist/database-BT7DVgSr.mjs +45 -0
- package/dist/{database-C3E9PZSx.mjs → database-Kq2AL5jH.mjs} +1 -1
- package/dist/dataset-BmvCxGoE.mjs +66 -0
- package/dist/{db-BRHPjshe.mjs → db-C8lj73Dz.mjs} +7 -7
- package/dist/delete-09O7BTNw.mjs +44 -0
- package/dist/{delete-Ci0aDYpf.mjs → delete-CYgNpHl7.mjs} +4 -4
- package/dist/{delete-G6EiGn2Q.mjs → delete-D_ZNoYVv.mjs} +4 -4
- package/dist/{delete-BxBadE3q.mjs → delete-HWeQtc4M.mjs} +4 -4
- package/dist/delete-I4eFpsed.mjs +44 -0
- package/dist/{delete-DMETa-37.mjs → delete-My8TX-B2.mjs} +4 -4
- package/dist/{delete-CQWCfqHf.mjs → delete-qwdN0N7e.mjs} +4 -4
- package/dist/delete-runtime-BbmRg_in.mjs +55 -0
- package/dist/{delete-table-N4rZtt1T.mjs → delete-table-BCvjX7bh.mjs} +4 -4
- package/dist/{dependencies-edN0P1SS.mjs → dependencies-BAE4YPXX.mjs} +5 -5
- package/dist/dependency-CIam7zmr.mjs +15 -0
- package/dist/dependency-DzLH3J8P.mjs +165 -0
- package/dist/dependency-zElFM-os.mjs +111 -0
- package/dist/dependents-Dv6tLdSs.mjs +52 -0
- package/dist/{dirty-U51bMoCP.mjs → dirty-CZORg0i0.mjs} +5 -5
- package/dist/discard-values-DKnP-JHr.mjs +55 -0
- package/dist/{document-CA0Q6lqu.mjs → document-C18b5rM6.mjs} +1 -1
- package/dist/{document-BHpLJbKU.mjs → document-DFCj1Az_.mjs} +2 -1
- package/dist/document-uxz96Lah.mjs +20 -0
- package/dist/{download-BJA6k-e6.mjs → download-BImtTll0.mjs} +2 -2
- package/dist/{eid-BtlRU1E0.mjs → eid-D0FxhT9H.mjs} +11 -10
- package/dist/entity-DWp9WJbU.mjs +20 -0
- package/dist/entry-flags-3sDWwa90.mjs +42 -0
- package/dist/{events-B5rnOo-L.mjs → events-BzCjVA3-.mjs} +4 -4
- package/dist/execute-BhHbkBqf.mjs +45 -0
- package/dist/export-CjqjDnaZ.mjs +74 -0
- package/dist/export-flags-BETJHNcw.mjs +81 -0
- package/dist/export-preflight-DzvIP6TB.mjs +35 -0
- package/dist/{field-CcN4oZy6.mjs → field-5nivEfd6.mjs} +33 -3
- package/dist/field-fBpiGiqr.mjs +21 -0
- package/dist/field-wmN6raOG.mjs +128 -0
- package/dist/{fields-zQ6O_W_H.mjs → fields-C-au1eLO.mjs} +6 -6
- package/dist/filter-flags-BIFcA2TT.mjs +72 -0
- package/dist/fks-83QIm8xb.mjs +36 -0
- package/dist/{get-93wuhTn2.mjs → get-BMHbEGbr.mjs} +4 -4
- package/dist/{get-DXwlZjw0.mjs → get-BTCOzSkl.mjs} +3 -3
- package/dist/{get-CekXFP3x.mjs → get-BawLhSwW.mjs} +3 -3
- package/dist/{get-BLjcCXp8.mjs → get-BjqqFG2m.mjs} +3 -3
- package/dist/{get-is8x5f2n.mjs → get-C-R_Fdsi.mjs} +3 -3
- package/dist/{get-DC_huYD8.mjs → get-C73V2KsB.mjs} +5 -5
- package/dist/{get-CG6G-mzV.mjs → get-C9sq2boy.mjs} +5 -5
- package/dist/{get-Cf6a4fFN.mjs → get-Cggv6yLC.mjs} +4 -4
- package/dist/{get-xPv7e5Ez.mjs → get-CkXc0Xld.mjs} +5 -5
- package/dist/{get-BLcS4il2.mjs → get-CqNEVAX_2.mjs} +3 -3
- package/dist/{get-DhpMuTSt.mjs → get-D7h7uH4k.mjs} +5 -5
- package/dist/get-DGmE5fmp.mjs +31 -0
- package/dist/{get-EFsmL4le.mjs → get-DTTsPd-c.mjs} +5 -5
- package/dist/{get-CeSQptdl.mjs → get-DXBXhPrU.mjs} +5 -5
- package/dist/{get-CTp5l7aU.mjs → get-D_v1IAL1.mjs} +3 -3
- package/dist/{get-BDrmBZ1z.mjs → get-DkzO3G5p.mjs} +5 -5
- package/dist/{get-Dg-S07ri.mjs → get-Dvr_69L7.mjs} +3 -3
- package/dist/get-NOMvMvYJ.mjs +36 -0
- package/dist/{get-BSoMWp4t2.mjs → get-YPDWhgm_2.mjs} +4 -4
- package/dist/{get-CwiJWeH4.mjs → get-Z36_0HX_.mjs} +4 -4
- package/dist/{get-run-DwY4sFGy.mjs → get-run-v1QHn-Mx.mjs} +4 -4
- package/dist/{git-sync-BwBRmEhE.mjs → git-sync-COokpYgc.mjs} +12 -3
- package/dist/git-sync-DspFahwV.mjs +165 -0
- package/dist/git-sync-VAqASCQ5.mjs +29 -0
- package/dist/glossary-BlNCrYbw.mjs +30 -0
- package/dist/glossary-Brnk2PBi.mjs +14 -0
- package/dist/glossary-LmZWwCNP.mjs +21 -0
- package/dist/graph-B6OliqnW.mjs +34 -0
- package/dist/{group-YQQ5GIcP.mjs → group-bpD_KcjA.mjs} +1 -1
- package/dist/{has-remote-changes-DE2_14FK.mjs → has-remote-changes-iTRCU9j0.mjs} +4 -4
- package/dist/{import-Cs7wk058.mjs → import-CdSs5CtT.mjs} +19 -8
- package/dist/{input-DEvkIjGr.mjs → input-D8qW-KtR.mjs} +6 -2
- package/dist/{is-dirty-XqDfqXGi.mjs → is-dirty-B5fj9NeS.mjs} +2 -2
- package/dist/{items-BloAjPwA.mjs → items-BxWnNEh7.mjs} +8 -8
- package/dist/{key-PYetuQ13.mjs → key-BynJSK9u.mjs} +1 -1
- package/dist/{library-Dgq_5BFh.mjs → library-BHHgurW0.mjs} +5 -5
- package/dist/{library-PGCfm0UA.mjs → library-BOv5SY24.mjs} +1 -1
- package/dist/{library-BPIzb3K_.mjs → library-Ck0EK5bi.mjs} +4 -2
- package/dist/{list-D9d5ocYi.mjs → list-BPMOLrwn.mjs} +5 -5
- package/dist/{list-D04uiS3F.mjs → list-BTcEm4td.mjs} +3 -3
- package/dist/{list-CghNKfYJ.mjs → list-BTgAbqeS.mjs} +4 -4
- package/dist/{list-3ErmGdY0.mjs → list-Bop1NTbU.mjs} +6 -6
- package/dist/{list-yV6CyPzn.mjs → list-By9XJRiv.mjs} +3 -3
- package/dist/list-CNC-XHbN.mjs +35 -0
- package/dist/{list-CUJ1wem9.mjs → list-CPWgBkPa.mjs} +4 -4
- package/dist/{list-sdCIS2Df.mjs → list-Cpa0Se7M.mjs} +5 -5
- package/dist/list-DA9KsA0o.mjs +101 -0
- package/dist/{list-VzrtA9lt.mjs → list-DE9gYY3I.mjs} +3 -3
- package/dist/{list-CUXlZiS1.mjs → list-DFJt2-fY.mjs} +4 -4
- package/dist/{list-BZnf3RmA.mjs → list-DUcnAb1h.mjs} +3 -3
- package/dist/{list-vsXIMssK.mjs → list-DW4-u7eO.mjs} +5 -5
- package/dist/{list-f8Csdjyc.mjs → list-DbXnSL2x.mjs} +5 -5
- package/dist/list-DgsM9YQX.mjs +28 -0
- package/dist/{list-BfLo1xI8.mjs → list-Dzzt6Yee.mjs} +3 -3
- package/dist/{list-CZCaqPoo.mjs → list-ZHLsjxXg.mjs} +6 -6
- package/dist/{list-Bzm5mXRo.mjs → list-e7yvJYMw.mjs} +3 -3
- package/dist/{list-DboUvg-Y.mjs → list-hN_Tu2T6.mjs} +6 -6
- package/dist/{list-DuJezLm_.mjs → list-zyKxxNvn.mjs} +3 -3
- package/dist/{login-Vw51Gts5.mjs → login-B7nGQDZK.mjs} +6 -6
- package/dist/{logout-BDIqoVhv.mjs → logout-pZffAh1G.mjs} +2 -2
- package/dist/{measure-LY9Tp9QZ.mjs → measure-AtnrCTCC.mjs} +6 -6
- package/dist/moderation-review-BdqEH6N1.mjs +31 -0
- package/dist/{notification-DVrLkjFT.mjs → notification-DOYdl0ao.mjs} +1 -1
- package/dist/{parameter-values-DWjmO7Ai.mjs → parameter-values-CxTkEjCs.mjs} +3 -3
- package/dist/{parse-enum-Dc0dMZ3P.mjs → parse-enum-CLIXMsd8.mjs} +1 -1
- package/dist/parse-id-7ja3HUdB.mjs +13 -0
- package/dist/{parse-ref-DTDld_LJ.mjs → parse-ref-Cw5fa4FI.mjs} +1 -1
- package/dist/parse-text-T0lTXzTZ.mjs +11 -0
- package/dist/{path-BUUAGYO5.mjs → path-DM4vyihl.mjs} +4 -4
- package/dist/{poll-CZeXepUQ.mjs → poll-Dz4tUm2f.mjs} +2 -2
- package/dist/{preflight-DcULqq8E.mjs → preflight-DaZ2z2C1.mjs} +3 -3
- package/dist/{process-CTrfxxaC.mjs → process-D0HdqZ3r.mjs} +1 -1
- package/dist/{publish-qVFmJQ1E.mjs → publish-C0HCL04a.mjs} +4 -4
- package/dist/{pulse-x0gFxWfG.mjs → pulse-D1uh8UIU.mjs} +1 -1
- package/dist/{query-Cq1lmqL5.mjs → query-BC-C6efK.mjs} +14 -33
- package/dist/query-BKtMP5eH.mjs +13 -0
- package/dist/query-CAFPlqfi.mjs +329 -0
- package/dist/remapping-CgA6UJGU.mjs +53 -0
- package/dist/{remove-collection-DBqh2Lqm.mjs → remove-collection-DoctJa9g.mjs} +5 -5
- package/dist/{render-Gx1hR7IF.mjs → render-Bvm9mta6.mjs} +2 -2
- package/dist/{replace-CujInVY9.mjs → replace-CaFJd9fO.mjs} +4 -4
- package/dist/rescan-values-7VOGCLMe.mjs +32 -0
- package/dist/{rescan-values-HypqBCSK.mjs → rescan-values-sJRwcHsk.mjs} +5 -5
- package/dist/{run-DEkQSOQa.mjs → run-COHDQ5J4.mjs} +3 -3
- package/dist/{run-b3jyF29q.mjs → run-RXpFlDAB.mjs} +4 -4
- package/dist/{runs-GHqHLGy4.mjs → runs-CUYdCKiE.mjs} +5 -5
- package/dist/{runtime-nCPku2nN.mjs → runtime-B8RtMb4B.mjs} +21 -82
- package/dist/{schema-tables-B5L05Y1L.mjs → schema-tables-CO5qyZBe.mjs} +6 -6
- package/dist/{schemas-Clx26p_4.mjs → schemas-CzHHgDdF.mjs} +4 -4
- package/dist/search-BWb052_b.mjs +131 -0
- package/dist/search-Cc9vHNae.mjs +85 -0
- package/dist/{segment-DiRJcbam.mjs → segment-C_rsUkHK.mjs} +6 -6
- package/dist/{send-DIHkDNBN.mjs → send-C-3bkpni.mjs} +3 -3
- package/dist/{set-D77qUZML.mjs → set-BDkT37OT.mjs} +4 -4
- package/dist/{set-active-DCdFgD0O.mjs → set-active-CDJTfQEc.mjs} +3 -3
- package/dist/set-sensitivity-DVrINHde.mjs +57 -0
- package/dist/{setting-DR9bj232.mjs → setting-CoLzd08x.mjs} +4 -4
- package/dist/{setup-DGa2LLEp.mjs → setup-C4F4XYbU.mjs} +3 -3
- package/dist/{signal-k7cm5N6h.mjs → signal-CxWeLszu.mjs} +1 -1
- package/dist/{skill-list-DAvGGHzS.mjs → skill-list-BgihWuPf.mjs} +2 -2
- package/dist/{skills-CqtNuSXM.mjs → skills-4qDjKRSk.mjs} +2 -2
- package/dist/{skills-CCn7cyMP.mjs → skills-BWEFRpUj.mjs} +3 -3
- package/dist/snippet-CYd8D9SK.mjs +19 -0
- package/dist/{stash-BTtsV0AG.mjs → stash-CZ1x0rox.mjs} +6 -6
- package/dist/{status-XgSS3StV.mjs → status-BM6eYW7I.mjs} +3 -3
- package/dist/{status-CW7Dt-nV.mjs → status-gqpPZvue.mjs} +7 -7
- package/dist/{subscription-CofRU47d.mjs → subscription-pSuO241O.mjs} +6 -6
- package/dist/{subscriptions-DCuuPF6U.mjs → subscriptions-n5zJ9rYZ.mjs} +6 -6
- package/dist/{summary-uGlgKE3C.mjs → summary-DvIf2EiO.mjs} +5 -5
- package/dist/sync-schema-Cc21crxQ.mjs +32 -0
- package/dist/{sync-schema-Cu9rD3eH.mjs → sync-schema-D1t8rhdQ.mjs} +6 -6
- package/dist/sync-task-CXFoqlpF.mjs +53 -0
- package/dist/{table-DfuY0N8e.mjs → table-Ci6bhZkb.mjs} +35 -12
- package/dist/table-CxvaDiIZ.mjs +155 -0
- package/dist/table-Dc0dLfyg.mjs +26 -0
- package/dist/table-selector-flags-BVZvnhUa.mjs +42 -0
- package/dist/text-DaNkPRwt.mjs +6 -0
- package/dist/timeline-BqU5sOb6.mjs +21 -0
- package/dist/{timeline-event-D-h0A_oh.mjs → timeline-event-jn1SOKd4.mjs} +6 -6
- package/dist/transform-BUIlFqpv.mjs +28 -0
- package/dist/{transform-CtqB1WYo.mjs → transform-CNBIV7No.mjs} +1 -1
- package/dist/transform-job-DsbY9mme.mjs +22 -0
- package/dist/{transform-tag-BLp_p9J-.mjs → transform-tag-C0jzV6Dk.mjs} +5 -5
- package/dist/{transforms-n2IwEcbU.mjs → transforms-DwTy_Quh.mjs} +5 -5
- package/dist/tree-p2j6IVy-.mjs +34 -0
- package/dist/{unpublish-DVQCAa3g.mjs → unpublish-B-961jX1.mjs} +3 -3
- package/dist/unreferenced-Dxy-aYI7.mjs +36 -0
- package/dist/{update-CnkPYL2i.mjs → update-BFYRBbRu.mjs} +6 -6
- package/dist/{update-ChpOukqq.mjs → update-BGeaPntx.mjs} +5 -5
- package/dist/{update-NGq0yXZk.mjs → update-BnIEN390.mjs} +5 -5
- package/dist/{update-DffrdV4b.mjs → update-CALlEgIC.mjs} +4 -4
- package/dist/{update-DFdBeJwc.mjs → update-CHkVN69L.mjs} +13 -8
- package/dist/{update-oQeQyqKO.mjs → update-CKqL9PmU.mjs} +5 -5
- package/dist/{update-rFRPLlb6.mjs → update-CYGYUCFQ.mjs} +4 -4
- package/dist/update-CuQy2g51.mjs +52 -0
- package/dist/{update-B7CikkI0.mjs → update-D4TGE6FS.mjs} +7 -7
- package/dist/{update-D9H6Lh5U.mjs → update-D7xi-0bU.mjs} +4 -4
- package/dist/{update-DKO9HF1f.mjs → update-DK77vtFF.mjs} +6 -6
- package/dist/{update-CKDRuduL.mjs → update-DKDQTlnV.mjs} +5 -5
- package/dist/update-DXxJHC8y.mjs +41 -0
- package/dist/update-DiJK0uRG.mjs +181 -0
- package/dist/{update-CAsqNhDC.mjs → update-MD1Kwq1P.mjs} +4 -4
- package/dist/{update-dashcard-DvPqLJ3N.mjs → update-dashcard-DuTjOh14.mjs} +6 -6
- package/dist/{update-DScUzKLI.mjs → update-hvO4VpfZ.mjs} +7 -7
- package/dist/{update-D4ggtuG4.mjs → update-qDZvnwvf.mjs} +7 -7
- package/dist/{update-C05J2nZ2.mjs → update-tltXCUwR.mjs} +4 -4
- package/dist/{upgrade-BRgw0fvn.mjs → upgrade-Ca-Ss5jb.mjs} +4 -4
- package/dist/{upload-Do2PBSeH.mjs → upload-C2fhpKkP.mjs} +2 -2
- package/dist/upload-Dw7mVr9u.mjs +13 -0
- package/dist/{upload-BrfbcbBW.mjs → upload-t6dkccqn.mjs} +3 -3
- package/dist/{uuid-B4eij1d7.mjs → uuid-BMlJZT8z.mjs} +2 -2
- package/dist/{validate-xR_MHBNR.mjs → validate-D7e110oU.mjs} +1 -1
- package/dist/{validate-query-D6_ad-Gi.mjs → validate-query-BzbZmenf.mjs} +7 -3
- package/dist/{values-xgOftPq5.mjs → values-CXN4xTTh.mjs} +5 -5
- package/dist/verify-CPVfwKSu.mjs +38 -0
- package/dist/verify-flags-CMpRkMPa.mjs +58 -0
- package/dist/verify-k-JB-k3D.mjs +38 -0
- package/dist/{verify-DTOA_wVM.mjs → verify-t-CEmvoG.mjs} +3 -3
- package/dist/{wait-BjeFgR13.mjs → wait-KSkq7kKW.mjs} +6 -6
- package/dist/{wait-flags-BCeCnaz3.mjs → wait-flags-KX7NHdj4.mjs} +2 -2
- package/dist/{window-DSb1tqSe.mjs → window-CI_QD04s.mjs} +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +18 -11
- package/skill-data/dashboard/SKILL.md +1 -1
- package/skill-data/data-action/SKILL.md +125 -0
- package/skill-data/document/SKILL.md +12 -1
- package/skill-data/git-sync/SKILL.md +61 -9
- package/skill-data/mbql/SKILL.md +5 -0
- package/skill-data/metadata/SKILL.md +36 -6
- package/skill-data/native-sql/SKILL.md +1 -1
- package/dist/body-Cu94pH4P.mjs +0 -17
- package/dist/card-ByOzVxpI.mjs +0 -24
- package/dist/collection-BGbW7u_Q.mjs +0 -20
- package/dist/dashboard-Bzjz2v6u.mjs +0 -33
- package/dist/database-JtHTqSpq.mjs +0 -26
- package/dist/delete-runtime-BKEzJn22.mjs +0 -49
- package/dist/document-DqJ7Cysa.mjs +0 -19
- package/dist/export-DO2josC0.mjs +0 -63
- package/dist/field-CHZByaXa.mjs +0 -18
- package/dist/field-fDtIrY6D.mjs +0 -80
- package/dist/get-yHIEezeG.mjs +0 -31
- package/dist/git-sync-NhfLSZA6.mjs +0 -28
- package/dist/git-sync-TjX1r_wF.mjs +0 -136
- package/dist/list-DgteFn01.mjs +0 -34
- package/dist/parse-id-whJX4DAb.mjs +0 -10
- package/dist/query-BPtIy79s.mjs +0 -114
- package/dist/query-result-E4Q-Gra6.mjs +0 -15
- package/dist/search-DxiuY5EV.mjs +0 -97
- package/dist/selectors-rEFuyXPZ.mjs +0 -35
- package/dist/snippet-g9JTDxqu.mjs +0 -19
- package/dist/sync-task-BXeWuARG.mjs +0 -37
- package/dist/table-C6h4tIRw.mjs +0 -37
- package/dist/table-Di-EY7pg.mjs +0 -18
- package/dist/timeline-D7EsWZm6.mjs +0 -21
- package/dist/transform-8XK1LIgC.mjs +0 -28
- package/dist/transform-job-CTizQkWy.mjs +0 -22
- package/dist/tree-cqxiDh2b.mjs +0 -26
- package/dist/upload-VXBFKzLT.mjs +0 -13
|
@@ -1,22 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { at as ConfigError, ct as NetworkError, ft as ValidationError, lt as ResponseShapeError, mt as formatZodIssue, n as methodRequirements, ot as InternalError, pt as errorMessage, ut as TimeoutError } from "./cli.mjs";
|
|
2
2
|
import { n as Notification, r as NotificationCardPayload, t as CARD_PAYLOAD_TYPE } from "./notification-DaA4bBHW.mjs";
|
|
3
|
-
import { $ as
|
|
4
|
-
import { n as throwIfAborted, r as untilAborted, t as combineAborts } from "./signal-
|
|
5
|
-
import {
|
|
3
|
+
import { $ as CapabilityError, B as assertCredentialHeaderSafe, G as normalizeUrl, H as credentialSecrets, I as isRetryableStatus, J as checkFeatures, L as JSON_CONTENT_TYPE, M as buildNetworkError, N as isConnectionClosed, P as HttpError, Q as probeServer, R as parseJson, V as credentialAuthHeader, X as createServerProfile, Z as PROBE_PATH, z as parseJsonOrPlain } from "./runtime-B8RtMb4B.mjs";
|
|
4
|
+
import { n as throwIfAborted, r as untilAborted, t as combineAborts } from "./signal-CxWeLszu.mjs";
|
|
5
|
+
import { f as FieldWithDataSensitivity, h as fieldRemappedValueSchema, m as fieldDetailSchema, n as FieldBaseType, o as FieldSearchMatches, s as FieldSemanticType, u as FieldValues } from "./field-5nivEfd6.mjs";
|
|
6
6
|
import { a as TemporalUnit, r as ParameterValues } from "./parameter-Celg0wZa.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { t as
|
|
7
|
+
import { r as PivotExportFormat, t as DatasetQuery } from "./query-BKtMP5eH.mjs";
|
|
8
|
+
import { a as CardQueryResult, t as Card } from "./card-P5mBknsl.mjs";
|
|
9
|
+
import { b as TableVisibilityType, p as TableQueryMetadata, s as TableDataLayerTier, t as Table, u as TableForeignKey, v as TableSelectors } from "./table-Ci6bhZkb.mjs";
|
|
10
|
+
import { t as Database } from "./database-BT7DVgSr.mjs";
|
|
10
11
|
import { t as Snippet } from "./snippet-CyKAgIZl.mjs";
|
|
11
|
-
import {
|
|
12
|
+
import { o as compiledQuerySchema, r as QueryMetadata } from "./dataset-BmvCxGoE.mjs";
|
|
13
|
+
import { c as CollectionItem, m as CollectionTreeNode, r as Collection } from "./collection-D3KXhvnc.mjs";
|
|
12
14
|
import { t as ContentTranslationUploadResult } from "./content-translation-BrHOrmj9.mjs";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
15
|
+
import { l as Dashcard, o as DashboardDetail, r as DashboardCopy, t as Dashboard } from "./dashboard-Phz3XpRM.mjs";
|
|
16
|
+
import { a as DataActionExecuteResult, s as dataActionSchema } from "./data-action-DZxVB_hD.mjs";
|
|
17
|
+
import { r as pollUntil } from "./poll-Dz4tUm2f.mjs";
|
|
18
|
+
import { i as DependencyEntity, s as DependencyGraph, t as BreakingSource, u as DependencyNode } from "./dependency-DzLH3J8P.mjs";
|
|
19
|
+
import { t as Document } from "./document-DFCj1Az_.mjs";
|
|
16
20
|
import { i as EidTranslateResult } from "./eid-translation-zEHtr5Oc.mjs";
|
|
17
|
-
import { c as
|
|
18
|
-
import {
|
|
21
|
+
import { c as SyncRemoteChanges, d as SyncTask, i as SyncExportPreflight, l as SyncSettingsUpdateResult, m as isSyncTaskTerminal, n as SyncDirtyItem, t as SyncBranchCreated } from "./git-sync-COokpYgc.mjs";
|
|
22
|
+
import { t as Glossary } from "./glossary-BlNCrYbw.mjs";
|
|
23
|
+
import { a as libraryWireSchema, i as LibraryPublishTablesInput, n as LibraryCollectionInfo, o as toLibrary } from "./library-Ck0EK5bi.mjs";
|
|
19
24
|
import { t as Measure } from "./measure-CtfjqJFP.mjs";
|
|
25
|
+
import { r as ModerationReviewCreateInput, t as ModerationReview } from "./moderation-review-BdqEH6N1.mjs";
|
|
20
26
|
import { t as Pulse } from "./pulse-Dz0ocv0l.mjs";
|
|
21
27
|
import { a as TransformDagTransform, d as TransformTarget, g as transformRowSchema, h as transformDetailSchema, i as TransformDagRunResult, l as TransformRunSummary, m as isTransformRunTerminal, o as TransformRun, p as isTransformRunFailed, u as TransformSourceTableEntry } from "./transform-DiW7bREn.mjs";
|
|
22
28
|
import { r as SearchResult } from "./search-BAXg-EJw.mjs";
|
|
@@ -349,43 +355,16 @@ async function readBodyForError(response) {
|
|
|
349
355
|
}
|
|
350
356
|
}
|
|
351
357
|
//#endregion
|
|
352
|
-
//#region ../client/src/
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
]);
|
|
363
|
-
const VirtualField = z.object({
|
|
364
|
-
id: z.union([z.number().int(), FieldRef]),
|
|
365
|
-
table_id: z.string(),
|
|
366
|
-
name: z.string(),
|
|
367
|
-
display_name: z.string(),
|
|
368
|
-
base_type: FieldBaseType,
|
|
369
|
-
semantic_type: FieldSemanticType.nullable(),
|
|
370
|
-
fk_target_field_id: z.number().int().nullable().optional()
|
|
371
|
-
}).loose();
|
|
372
|
-
const VirtualTable = z.object({
|
|
373
|
-
id: z.string(),
|
|
374
|
-
db_id: z.number().int(),
|
|
375
|
-
display_name: z.string(),
|
|
376
|
-
schema: z.string(),
|
|
377
|
-
description: z.string().nullable(),
|
|
378
|
-
type: CardType,
|
|
379
|
-
moderated_status: z.string().nullable(),
|
|
380
|
-
entity_id: z.string().nullable(),
|
|
381
|
-
fields: z.array(VirtualField)
|
|
382
|
-
}).loose();
|
|
383
|
-
const QueryMetadata = z.object({
|
|
384
|
-
databases: z.array(Database),
|
|
385
|
-
tables: z.array(z.union([TableQueryMetadata, VirtualTable])),
|
|
386
|
-
fields: z.array(Field),
|
|
387
|
-
snippets: z.array(Snippet)
|
|
388
|
-
}).loose();
|
|
358
|
+
//#region ../client/src/resources/pivot-export.ts
|
|
359
|
+
const PivotedExportsSetting = z.object({ "enable-pivoted-exports": z.boolean() });
|
|
360
|
+
/**
|
|
361
|
+
* Refuse a pivoted export the server would answer with plain rows: a JSON export keeps only the
|
|
362
|
+
* ungrouped rows, and an admin can turn pivoted CSV and XLSX exports off.
|
|
363
|
+
*/
|
|
364
|
+
async function assertPivotedExport(transport, format, options) {
|
|
365
|
+
if (!PivotExportFormat.safeParse(format).success) throw new ConfigError(`a ${format} export cannot be pivoted; only ${PivotExportFormat.options.join(" and ")} can`);
|
|
366
|
+
if (!(await transport.requestParsed(PivotedExportsSetting, "/api/session/properties", { ...options }))["enable-pivoted-exports"]) throw new ConfigError("the server has pivoted exports turned off (the enable-pivoted-exports setting), so it would export the plain rows");
|
|
367
|
+
}
|
|
389
368
|
//#endregion
|
|
390
369
|
//#region ../client/src/resources/card.ts
|
|
391
370
|
const CardApiList = z.array(Card);
|
|
@@ -442,15 +421,22 @@ function cardResource(transport) {
|
|
|
442
421
|
});
|
|
443
422
|
}
|
|
444
423
|
/**
|
|
445
|
-
* Run a
|
|
446
|
-
* form-encoded body and answers bytes, so a caller
|
|
424
|
+
* Run the query associated with a Card, and return its results as a file in the specified
|
|
425
|
+
* format. Unlike `query`, this endpoint takes a form-encoded body and answers bytes, so a caller
|
|
426
|
+
* consumes the stream rather than a value. A pivot the server would answer with plain rows (a
|
|
427
|
+
* JSON export, or pivoted exports turned off) is refused. `csv_include_bom` opens a CSV with a
|
|
428
|
+
* UTF-8 byte order mark; a server without it drops the key silently, so asking for one is refused
|
|
429
|
+
* there before the wire.
|
|
447
430
|
*/
|
|
448
431
|
async function exportQuery(id, format, params, options = {}) {
|
|
449
432
|
await transport.require("card.exportQuery", options);
|
|
433
|
+
await transport.requireFeatures(params.csv_include_bom ? ["exportCsvByteOrderMark"] : [], options);
|
|
434
|
+
if (params.pivot_results) await assertPivotedExport(transport, format, options);
|
|
450
435
|
const body = new URLSearchParams({
|
|
451
436
|
parameters: JSON.stringify(params.parameters),
|
|
452
437
|
format_rows: String(params.format_rows),
|
|
453
|
-
pivot_results: String(params.pivot_results)
|
|
438
|
+
pivot_results: String(params.pivot_results),
|
|
439
|
+
csv_include_bom: String(params.csv_include_bom)
|
|
454
440
|
});
|
|
455
441
|
return transport.requestStream(`/api/card/${id}/query/${format}`, {
|
|
456
442
|
...options,
|
|
@@ -534,20 +520,20 @@ function refPath(ref) {
|
|
|
534
520
|
return encodeURIComponent(ref);
|
|
535
521
|
}
|
|
536
522
|
/**
|
|
537
|
-
* List
|
|
538
|
-
* projection. `Collection` pins `type`, `namespace` and `authority_level`
|
|
539
|
-
* consumer reading a few fields off every collection on the instance narrows
|
|
540
|
-
* carrying a server value outside those sets then costs nothing to a caller
|
|
541
|
-
* field.
|
|
523
|
+
* List every collection the caller can read, the Library and its children among them, parsing each
|
|
524
|
+
* through the caller's own projection. `Collection` pins `type`, `namespace` and `authority_level`
|
|
525
|
+
* to closed enums, so a consumer reading a few fields off every collection on the instance narrows
|
|
526
|
+
* here: one collection carrying a server value outside those sets then costs nothing to a caller
|
|
527
|
+
* that never reads the field.
|
|
542
528
|
*/
|
|
543
|
-
async function
|
|
544
|
-
return transport.requestParsed(z.array(schema), "/api/collection", {
|
|
545
|
-
...options,
|
|
546
|
-
query: { "include-library": true }
|
|
547
|
-
});
|
|
529
|
+
async function listCollectionsAs(transport, schema, options = {}) {
|
|
530
|
+
return transport.requestParsed(z.array(schema), "/api/collection", { ...options });
|
|
548
531
|
}
|
|
549
532
|
function collectionResource(transport) {
|
|
550
|
-
/**
|
|
533
|
+
/**
|
|
534
|
+
* List collections. `filter` picks a server-side preset: everything, archived, or personal. Every
|
|
535
|
+
* preset includes the Library collections that match it.
|
|
536
|
+
*/
|
|
551
537
|
async function list(params = {}, options = {}) {
|
|
552
538
|
await transport.require("collection.list", options);
|
|
553
539
|
return {
|
|
@@ -558,18 +544,6 @@ function collectionResource(transport) {
|
|
|
558
544
|
total: null
|
|
559
545
|
};
|
|
560
546
|
}
|
|
561
|
-
/**
|
|
562
|
-
* List collections including the Library and its children, which the plain listing omits.
|
|
563
|
-
* The Library's own children carry neither `type` nor `is_remote_synced`, so this is where a
|
|
564
|
-
* caller resolves both.
|
|
565
|
-
*/
|
|
566
|
-
async function listWithLibrary(options = {}) {
|
|
567
|
-
await transport.require("collection.listWithLibrary", options);
|
|
568
|
-
return {
|
|
569
|
-
data: await listCollectionsWithLibrary(transport, Collection, options),
|
|
570
|
-
total: null
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
547
|
/** Get one collection by id, entity id, or the `root`/`trash` alias. */
|
|
574
548
|
async function get(ref, options = {}) {
|
|
575
549
|
await transport.require("collection.get", options);
|
|
@@ -584,7 +558,11 @@ function collectionResource(transport) {
|
|
|
584
558
|
body: params
|
|
585
559
|
});
|
|
586
560
|
}
|
|
587
|
-
/**
|
|
561
|
+
/**
|
|
562
|
+
* Update a collection, patching the fields the body carries. The server reads an absent
|
|
563
|
+
* `archived` as `false`, so a patch without it restores an archived collection, and a patch that
|
|
564
|
+
* moves a collection into the trash ignores `parent_id`.
|
|
565
|
+
*/
|
|
588
566
|
async function update(ref, params, options = {}) {
|
|
589
567
|
await transport.require("collection.update", options);
|
|
590
568
|
return transport.requestParsed(Collection, `/api/collection/${refPath(ref)}`, {
|
|
@@ -617,16 +595,18 @@ function collectionResource(transport) {
|
|
|
617
595
|
});
|
|
618
596
|
}
|
|
619
597
|
/** Fetch the collection hierarchy as a forest of nested nodes. */
|
|
620
|
-
async function tree(options = {}) {
|
|
598
|
+
async function tree(params = {}, options = {}) {
|
|
621
599
|
await transport.require("collection.tree", options);
|
|
622
600
|
return {
|
|
623
|
-
data: await transport.requestParsed(CollectionTreeApiList, "/api/collection/tree", {
|
|
601
|
+
data: await transport.requestParsed(CollectionTreeApiList, "/api/collection/tree", {
|
|
602
|
+
...options,
|
|
603
|
+
query: { "include-library": params["include-library"] }
|
|
604
|
+
}),
|
|
624
605
|
total: null
|
|
625
606
|
};
|
|
626
607
|
}
|
|
627
608
|
return {
|
|
628
609
|
list,
|
|
629
|
-
listWithLibrary,
|
|
630
610
|
get,
|
|
631
611
|
create,
|
|
632
612
|
update,
|
|
@@ -715,9 +695,13 @@ function dashboardResource(transport) {
|
|
|
715
695
|
}
|
|
716
696
|
/**
|
|
717
697
|
* Copy a dashboard, with its tabs and dashcards, into `collection_id` (root when absent). A deep
|
|
718
|
-
* copy duplicates
|
|
719
|
-
*
|
|
720
|
-
*
|
|
698
|
+
* copy duplicates its questions and metrics and references its models. With `is_deep_copy`
|
|
699
|
+
* false or absent the copy references every card, and a dashboard holding unarchived dashboard
|
|
700
|
+
* questions is refused. Archived cards, cards the caller cannot read, and every card on a
|
|
701
|
+
* dashcard whose main card the caller cannot read are left out and reported as `uncopied`, once
|
|
702
|
+
* per dashcard they sat on. A left-out main card takes its dashcard with it; a left-out series
|
|
703
|
+
* card stays on a dashcard whose main card is referenced and is dropped from one whose main card
|
|
704
|
+
* is duplicated. Action, link and placeholder dashcards are not copied.
|
|
721
705
|
*/
|
|
722
706
|
async function copy(id, params = {}, options = {}) {
|
|
723
707
|
await transport.require("dashboard.copy", options);
|
|
@@ -856,6 +840,81 @@ function stripEntityId(dashcard) {
|
|
|
856
840
|
};
|
|
857
841
|
}
|
|
858
842
|
//#endregion
|
|
843
|
+
//#region ../client/src/resources/data-action.ts
|
|
844
|
+
function dataActionResource(transport) {
|
|
845
|
+
async function readSchema(options) {
|
|
846
|
+
const { features } = await transport.server(options);
|
|
847
|
+
return dataActionSchema(features);
|
|
848
|
+
}
|
|
849
|
+
/** List the unarchived data actions the caller can see. `GET /api/action` answers a bare array. */
|
|
850
|
+
async function list(options = {}) {
|
|
851
|
+
await transport.require("dataAction.list", options);
|
|
852
|
+
const schema = await readSchema(options);
|
|
853
|
+
return {
|
|
854
|
+
data: await transport.requestParsed(z.array(schema), "/api/action", { ...options }),
|
|
855
|
+
total: null
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
/** Get one unarchived data action by id. */
|
|
859
|
+
async function get(id, options = {}) {
|
|
860
|
+
await transport.require("dataAction.get", options);
|
|
861
|
+
const schema = await readSchema(options);
|
|
862
|
+
return transport.requestParsed(schema, `/api/action/${id}`, { ...options });
|
|
863
|
+
}
|
|
864
|
+
/** Create a data action — a parameterized native query that writes to a database — in a collection. */
|
|
865
|
+
async function create(params, options = {}) {
|
|
866
|
+
await transport.require("dataAction.create", options);
|
|
867
|
+
const schema = await readSchema(options);
|
|
868
|
+
return transport.requestParsed(schema, "/api/action", {
|
|
869
|
+
...options,
|
|
870
|
+
method: "POST",
|
|
871
|
+
body: params
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
/** Update a data action by id, patching only the fields the body carries. */
|
|
875
|
+
async function update(id, params, options = {}) {
|
|
876
|
+
await transport.require("dataAction.update", options);
|
|
877
|
+
const schema = await readSchema(options);
|
|
878
|
+
return transport.requestParsed(schema, `/api/action/${id}`, {
|
|
879
|
+
...options,
|
|
880
|
+
method: "PUT",
|
|
881
|
+
body: params
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
/** Archive (soft-delete) a data action by id. Metabase models this as an update, not its own endpoint. */
|
|
885
|
+
async function archive(id, options = {}) {
|
|
886
|
+
await transport.require("dataAction.archive", options);
|
|
887
|
+
return update(id, { archived: true }, options);
|
|
888
|
+
}
|
|
889
|
+
/** Delete a data action by id, removing it and the dashboard buttons that run it. */
|
|
890
|
+
async function remove(id, options = {}) {
|
|
891
|
+
await transport.require("dataAction.delete", options);
|
|
892
|
+
await transport.requestRaw(`/api/action/${id}`, {
|
|
893
|
+
...options,
|
|
894
|
+
method: "DELETE",
|
|
895
|
+
expectContentType: "binary"
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
/** Execute a data action by id with parameter values keyed by parameter id. */
|
|
899
|
+
async function execute(id, params, options = {}) {
|
|
900
|
+
await transport.require("dataAction.execute", options);
|
|
901
|
+
return transport.requestParsed(DataActionExecuteResult, `/api/action/${id}/execute`, {
|
|
902
|
+
...options,
|
|
903
|
+
method: "POST",
|
|
904
|
+
body: params
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
return {
|
|
908
|
+
list,
|
|
909
|
+
get,
|
|
910
|
+
create,
|
|
911
|
+
update,
|
|
912
|
+
archive,
|
|
913
|
+
delete: remove,
|
|
914
|
+
execute
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
//#endregion
|
|
859
918
|
//#region ../client/src/resources/database.ts
|
|
860
919
|
const DatabaseApiList = z.object({
|
|
861
920
|
data: z.array(Database),
|
|
@@ -971,7 +1030,8 @@ function datasetResource(transport) {
|
|
|
971
1030
|
*/
|
|
972
1031
|
async function native(datasetQuery, params = {}, options = {}) {
|
|
973
1032
|
await transport.require("dataset.native", options);
|
|
974
|
-
|
|
1033
|
+
const { features } = await transport.server(options);
|
|
1034
|
+
return transport.requestParsed(compiledQuerySchema(features), "/api/dataset/native", {
|
|
975
1035
|
...options,
|
|
976
1036
|
method: "POST",
|
|
977
1037
|
body: {
|
|
@@ -994,18 +1054,33 @@ function datasetResource(transport) {
|
|
|
994
1054
|
});
|
|
995
1055
|
}
|
|
996
1056
|
/**
|
|
997
|
-
*
|
|
998
|
-
* bytes, so a caller consumes the stream rather than a value.
|
|
1057
|
+
* Execute a query and download the result data as a file in the specified format. Unlike
|
|
1058
|
+
* `query`, this endpoint answers bytes, so a caller consumes the stream rather than a value.
|
|
1059
|
+
* `visualization_settings` drive `format_rows` column formatting and, through
|
|
1060
|
+
* `pivot_table.column_split`, the layout `pivot_results` lays the rows out in. The server only
|
|
1061
|
+
* computes that layout for a query it runs as a pivot, which it reads from the query's own
|
|
1062
|
+
* `was-pivot`, so `pivot_results` sets it. A pivot the server would answer with plain rows (a
|
|
1063
|
+
* JSON export, or pivoted exports turned off) is refused. `csv_include_bom` opens a CSV with a
|
|
1064
|
+
* UTF-8 byte order mark; a server without it drops the key silently, so asking for one is refused
|
|
1065
|
+
* there before the wire.
|
|
999
1066
|
*/
|
|
1000
1067
|
async function exportQuery(format, params, options = {}) {
|
|
1001
1068
|
await transport.require("dataset.exportQuery", options);
|
|
1069
|
+
await transport.requireFeatures(params.csv_include_bom ? ["exportCsvByteOrderMark"] : [], options);
|
|
1070
|
+
if (params.pivot_results) await assertPivotedExport(transport, format, options);
|
|
1071
|
+
const exported = params.pivot_results ? {
|
|
1072
|
+
...params.query,
|
|
1073
|
+
"was-pivot": true
|
|
1074
|
+
} : params.query;
|
|
1002
1075
|
return transport.requestStream(`/api/dataset/${format}`, {
|
|
1003
1076
|
...options,
|
|
1004
1077
|
method: "POST",
|
|
1005
1078
|
body: {
|
|
1006
|
-
query:
|
|
1079
|
+
query: exported,
|
|
1080
|
+
visualization_settings: params.visualization_settings,
|
|
1007
1081
|
format_rows: params.format_rows,
|
|
1008
|
-
pivot_results: params.pivot_results
|
|
1082
|
+
pivot_results: params.pivot_results,
|
|
1083
|
+
csv_include_bom: params.csv_include_bom
|
|
1009
1084
|
}
|
|
1010
1085
|
});
|
|
1011
1086
|
}
|
|
@@ -1017,133 +1092,18 @@ function datasetResource(transport) {
|
|
|
1017
1092
|
};
|
|
1018
1093
|
}
|
|
1019
1094
|
//#endregion
|
|
1020
|
-
//#region ../client/src/domain/dependency.ts
|
|
1021
|
-
const DependencyType = z.enum([
|
|
1022
|
-
"table",
|
|
1023
|
-
"card",
|
|
1024
|
-
"snippet",
|
|
1025
|
-
"transform",
|
|
1026
|
-
"dashboard",
|
|
1027
|
-
"document",
|
|
1028
|
-
"sandbox",
|
|
1029
|
-
"segment",
|
|
1030
|
-
"measure"
|
|
1031
|
-
]);
|
|
1032
|
-
const DependencyUsageType = z.enum([
|
|
1033
|
-
"table",
|
|
1034
|
-
"snippet",
|
|
1035
|
-
"transform",
|
|
1036
|
-
"dashboard",
|
|
1037
|
-
"document",
|
|
1038
|
-
"sandbox",
|
|
1039
|
-
"segment",
|
|
1040
|
-
"question",
|
|
1041
|
-
"model",
|
|
1042
|
-
"metric",
|
|
1043
|
-
"measure"
|
|
1044
|
-
]);
|
|
1045
|
-
const DependencyFindingErrorType = z.enum([
|
|
1046
|
-
"missing-column",
|
|
1047
|
-
"missing-table-alias",
|
|
1048
|
-
"missing-table",
|
|
1049
|
-
"missing-card",
|
|
1050
|
-
"duplicate-column",
|
|
1051
|
-
"syntax-error",
|
|
1052
|
-
"validation-exception-error"
|
|
1053
|
-
]);
|
|
1054
|
-
const DependencyErrorSourceType = z.enum([
|
|
1055
|
-
"table",
|
|
1056
|
-
"card",
|
|
1057
|
-
"transform"
|
|
1058
|
-
]);
|
|
1059
|
-
z.enum([
|
|
1060
|
-
"name",
|
|
1061
|
-
"location",
|
|
1062
|
-
"view-count"
|
|
1063
|
-
]);
|
|
1064
|
-
z.enum([
|
|
1065
|
-
"name",
|
|
1066
|
-
"location",
|
|
1067
|
-
"dependents-with-errors",
|
|
1068
|
-
"dependents-errors"
|
|
1069
|
-
]);
|
|
1070
|
-
const DependencyCollectionRef = z.object({
|
|
1071
|
-
id: CollectionId,
|
|
1072
|
-
name: z.string(),
|
|
1073
|
-
authority_level: CollectionAuthorityLevel.nullable(),
|
|
1074
|
-
is_personal: z.boolean().optional()
|
|
1075
|
-
}).loose();
|
|
1076
|
-
const DependencyContainerRef = z.object({
|
|
1077
|
-
id: z.number().int(),
|
|
1078
|
-
name: z.string()
|
|
1079
|
-
}).loose();
|
|
1080
|
-
const DependencyEntityData = z.object({
|
|
1081
|
-
name: z.string().nullable().optional(),
|
|
1082
|
-
display_name: z.string().nullable().optional(),
|
|
1083
|
-
description: z.string().nullable().optional(),
|
|
1084
|
-
type: CardType.nullable().optional(),
|
|
1085
|
-
display: z.string().nullable().optional(),
|
|
1086
|
-
database_id: z.number().int().nullable().optional(),
|
|
1087
|
-
db_id: z.number().int().nullable().optional(),
|
|
1088
|
-
schema: z.string().nullable().optional(),
|
|
1089
|
-
collection_id: CollectionId.nullable().optional(),
|
|
1090
|
-
collection: DependencyCollectionRef.nullable().optional(),
|
|
1091
|
-
dashboard_id: z.number().int().nullable().optional(),
|
|
1092
|
-
dashboard: DependencyContainerRef.nullable().optional(),
|
|
1093
|
-
document_id: z.number().int().nullable().optional(),
|
|
1094
|
-
document: DependencyContainerRef.nullable().optional(),
|
|
1095
|
-
table_id: z.number().int().nullable().optional(),
|
|
1096
|
-
view_count: z.number().int().nullable().optional()
|
|
1097
|
-
}).loose();
|
|
1098
|
-
const DependencyEntity = z.object({
|
|
1099
|
-
id: z.number().int(),
|
|
1100
|
-
type: DependencyType,
|
|
1101
|
-
data: DependencyEntityData
|
|
1102
|
-
}).loose();
|
|
1103
|
-
const DependencyNode = DependencyEntity.extend({ dependents_count: z.partialRecord(DependencyUsageType, z.number().int()).nullable() });
|
|
1104
|
-
const DependencyFindingError = z.object({
|
|
1105
|
-
id: z.number().int(),
|
|
1106
|
-
analyzed_entity_type: DependencyType,
|
|
1107
|
-
analyzed_entity_id: z.number().int(),
|
|
1108
|
-
error_type: DependencyFindingErrorType,
|
|
1109
|
-
error_detail: z.string().nullable().optional(),
|
|
1110
|
-
source_entity_type: DependencyErrorSourceType.nullable().optional(),
|
|
1111
|
-
source_entity_id: z.number().int().nullable().optional()
|
|
1112
|
-
}).loose();
|
|
1113
|
-
const BreakingSource = DependencyNode.extend({ dependents_errors: z.array(DependencyFindingError).nullable().optional() });
|
|
1114
|
-
const DependencyEdge = z.object({
|
|
1115
|
-
from_entity_type: DependencyType,
|
|
1116
|
-
from_entity_id: z.number().int(),
|
|
1117
|
-
to_entity_type: DependencyType,
|
|
1118
|
-
to_entity_id: z.number().int()
|
|
1119
|
-
}).loose();
|
|
1120
|
-
const DependencyGraph = z.object({
|
|
1121
|
-
nodes: z.array(DependencyNode),
|
|
1122
|
-
edges: z.array(DependencyEdge)
|
|
1123
|
-
}).loose();
|
|
1124
|
-
//#endregion
|
|
1125
1095
|
//#region ../client/src/resources/dependency.ts
|
|
1126
1096
|
const DependencyNodeApiList = z.array(DependencyNode);
|
|
1127
1097
|
const DependencyEntityApiList = z.array(DependencyEntity);
|
|
1128
|
-
const RENAMED_FILTERS = [
|
|
1129
|
-
"dependent-types",
|
|
1130
|
-
"dependent-card-types",
|
|
1131
|
-
"card-types",
|
|
1132
|
-
"include-personal-collections",
|
|
1133
|
-
"sort-column",
|
|
1134
|
-
"sort-direction"
|
|
1135
|
-
];
|
|
1136
|
-
function filterFeatures(params) {
|
|
1137
|
-
return RENAMED_FILTERS.some((key) => params[key] !== void 0) ? ["dependencyKebabCaseFilters"] : [];
|
|
1138
|
-
}
|
|
1139
1098
|
function dependencyResource(transport) {
|
|
1140
1099
|
/**
|
|
1141
1100
|
* The upstream dependency graph of one entity. `nodes` holds the starting entity plus every
|
|
1142
1101
|
* entity it depends on, directly or transitively; each edge runs from the dependent to what it
|
|
1143
|
-
* depends on.
|
|
1102
|
+
* depends on. A measure starts a graph only on a server with `measureDependencyGraph`.
|
|
1144
1103
|
*/
|
|
1145
1104
|
async function graph(type, id, options = {}) {
|
|
1146
1105
|
await transport.require("dependency.graph", options);
|
|
1106
|
+
if (type === "measure") await transport.requireFeatures(["measureDependencyGraph"], options);
|
|
1147
1107
|
return transport.requestParsed(DependencyGraph, "/api/ee/dependencies/graph", {
|
|
1148
1108
|
...options,
|
|
1149
1109
|
query: {
|
|
@@ -1160,7 +1120,6 @@ function dependencyResource(transport) {
|
|
|
1160
1120
|
*/
|
|
1161
1121
|
async function dependents(type, id, params = {}, options = {}) {
|
|
1162
1122
|
await transport.require("dependency.dependents", options);
|
|
1163
|
-
await transport.requireFeatures(filterFeatures(params), options);
|
|
1164
1123
|
return {
|
|
1165
1124
|
data: await transport.requestParsed(DependencyNodeApiList, "/api/ee/dependencies/graph/dependents", {
|
|
1166
1125
|
...options,
|
|
@@ -1187,7 +1146,6 @@ function dependencyResource(transport) {
|
|
|
1187
1146
|
*/
|
|
1188
1147
|
async function broken(type, id, params = {}, options = {}) {
|
|
1189
1148
|
await transport.require("dependency.broken", options);
|
|
1190
|
-
await transport.requireFeatures(filterFeatures(params), options);
|
|
1191
1149
|
return {
|
|
1192
1150
|
data: await transport.requestParsed(DependencyEntityApiList, "/api/ee/dependencies/graph/broken", {
|
|
1193
1151
|
...options,
|
|
@@ -1205,15 +1163,23 @@ function dependencyResource(transport) {
|
|
|
1205
1163
|
};
|
|
1206
1164
|
}
|
|
1207
1165
|
/**
|
|
1208
|
-
* Walk the entities
|
|
1209
|
-
*
|
|
1166
|
+
* Walk the entities that no readable, unarchived dependent depends on, one page at a time: an
|
|
1167
|
+
* entity used only by archived content, or by content the caller cannot read, is listed. `types`
|
|
1168
|
+
* and `card-types` narrow which kinds are listed, `query` matches against names and locations,
|
|
1210
1169
|
* `include-personal-collections` admits content in personal collections, and `sort-column` /
|
|
1211
|
-
* `sort-direction` order the result.
|
|
1212
|
-
*
|
|
1170
|
+
* `sort-direction` order the result. A `query` leaves sandboxes out, since they have no name or
|
|
1171
|
+
* location to match, so sandboxes alone with a `query` answer one empty page without a request.
|
|
1172
|
+
* This endpoint pages on the server, so the caller consumes pages and decides how far to pull.
|
|
1213
1173
|
*/
|
|
1214
1174
|
async function* unreferencedPages(params = {}, options = {}) {
|
|
1215
1175
|
await transport.require("dependency.unreferencedPages", options);
|
|
1216
|
-
|
|
1176
|
+
if (queryLeavesNoKind(params)) {
|
|
1177
|
+
yield {
|
|
1178
|
+
items: [],
|
|
1179
|
+
total: 0
|
|
1180
|
+
};
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1217
1183
|
yield* paginatePages(transport, "/api/ee/dependencies/graph/unreferenced", DependencyNode, {
|
|
1218
1184
|
query: itemListQuery(params),
|
|
1219
1185
|
...options.offset !== void 0 && { offset: options.offset },
|
|
@@ -1231,7 +1197,13 @@ function dependencyResource(transport) {
|
|
|
1231
1197
|
*/
|
|
1232
1198
|
async function* breakingPages(params = {}, options = {}) {
|
|
1233
1199
|
await transport.require("dependency.breakingPages", options);
|
|
1234
|
-
|
|
1200
|
+
if (queryLeavesNoKind(params)) {
|
|
1201
|
+
yield {
|
|
1202
|
+
items: [],
|
|
1203
|
+
total: 0
|
|
1204
|
+
};
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1235
1207
|
yield* paginatePages(transport, "/api/ee/dependencies/graph/breaking", BreakingSource, {
|
|
1236
1208
|
query: itemListQuery(params),
|
|
1237
1209
|
...options.offset !== void 0 && { offset: options.offset },
|
|
@@ -1248,9 +1220,14 @@ function dependencyResource(transport) {
|
|
|
1248
1220
|
breakingPages
|
|
1249
1221
|
};
|
|
1250
1222
|
}
|
|
1223
|
+
function queryLeavesNoKind(params) {
|
|
1224
|
+
const { query, types } = params;
|
|
1225
|
+
if (query === void 0 || types === void 0 || types.length === 0) return false;
|
|
1226
|
+
return types.every((type) => type === "sandbox");
|
|
1227
|
+
}
|
|
1251
1228
|
function itemListQuery(params) {
|
|
1252
1229
|
return {
|
|
1253
|
-
types: params.types,
|
|
1230
|
+
types: params.types === void 0 ? void 0 : [...new Set(params.types)],
|
|
1254
1231
|
"card-types": params["card-types"],
|
|
1255
1232
|
query: params.query,
|
|
1256
1233
|
"include-personal-collections": params["include-personal-collections"],
|
|
@@ -1417,21 +1394,39 @@ async function fetchOptionalParsed(client, path, schema, options = {}) {
|
|
|
1417
1394
|
//#region ../client/src/resources/field.ts
|
|
1418
1395
|
const FieldApiSummary = z.tuple([z.tuple([z.literal("count"), z.number().int()]), z.tuple([z.literal("distincts"), z.number().int()])]);
|
|
1419
1396
|
function fieldResource(transport) {
|
|
1420
|
-
/**
|
|
1397
|
+
/**
|
|
1398
|
+
* Get one field by id. A server that labels data sensitivity answers `data_sensitivity`, `null`
|
|
1399
|
+
* for an unlabelled field; any other answers the field without the key (`hasDataSensitivity`).
|
|
1400
|
+
*/
|
|
1421
1401
|
async function get(id, options = {}) {
|
|
1422
1402
|
await transport.require("field.get", options);
|
|
1423
|
-
|
|
1403
|
+
const { features } = await transport.server(options);
|
|
1404
|
+
return transport.requestParsed(fieldDetailSchema(features), `/api/field/${id}`, { ...options });
|
|
1424
1405
|
}
|
|
1425
1406
|
/**
|
|
1426
1407
|
* Update a field by id, patching only the fields the body carries. A `data_sensitivity` label is
|
|
1427
1408
|
* a person's call the server's classifier never overwrites, and `null` withdraws it so the
|
|
1428
1409
|
* classifier's own applies again; a server without the column would drop the key silently, so
|
|
1429
|
-
* the label is refused there before the wire.
|
|
1410
|
+
* the label is refused there before the wire. Answers the field the way `get` does.
|
|
1430
1411
|
*/
|
|
1431
1412
|
async function update(id, params, options = {}) {
|
|
1432
1413
|
await transport.require("field.update", options);
|
|
1433
1414
|
await transport.requireFeatures(params.data_sensitivity === void 0 ? [] : ["fieldDataSensitivity"], options);
|
|
1434
|
-
|
|
1415
|
+
const { features } = await transport.server(options);
|
|
1416
|
+
return transport.requestParsed(fieldDetailSchema(features), `/api/field/${id}`, {
|
|
1417
|
+
...options,
|
|
1418
|
+
method: "PUT",
|
|
1419
|
+
body: params
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Label a field's data sensitivity by hand. A person's label is never overwritten by the server's
|
|
1424
|
+
* classifier; `null` withdraws it, so whatever label the classifier wrote shows again. Answers
|
|
1425
|
+
* the field with the label it now carries.
|
|
1426
|
+
*/
|
|
1427
|
+
async function setDataSensitivity(id, params, options = {}) {
|
|
1428
|
+
await transport.require("field.setDataSensitivity", options);
|
|
1429
|
+
return transport.requestParsed(FieldWithDataSensitivity, `/api/field/${id}`, {
|
|
1435
1430
|
...options,
|
|
1436
1431
|
method: "PUT",
|
|
1437
1432
|
body: params
|
|
@@ -1439,8 +1434,11 @@ function fieldResource(transport) {
|
|
|
1439
1434
|
}
|
|
1440
1435
|
/**
|
|
1441
1436
|
* Search the values of `searchId` that contain `value`, case-insensitively, answering the
|
|
1442
|
-
* matching values of `id` paired with them
|
|
1443
|
-
* points at
|
|
1437
|
+
* matching values of `id` paired with them, ordered by value, at most `limit` of them. An FK on
|
|
1438
|
+
* either side is followed to the PK it points at, and a field that resolves to the same field as
|
|
1439
|
+
* `searchId` answers each value alone. Without `value`, the first `limit` values. A field with
|
|
1440
|
+
* custom display values answers every mapped value with its display value instead, matching
|
|
1441
|
+
* `value` against the display value, ignoring both `searchId` and `limit`.
|
|
1444
1442
|
*/
|
|
1445
1443
|
async function search(id, searchId, params, options = {}) {
|
|
1446
1444
|
await transport.require("field.search", options);
|
|
@@ -1454,11 +1452,13 @@ function fieldResource(transport) {
|
|
|
1454
1452
|
}
|
|
1455
1453
|
/**
|
|
1456
1454
|
* The value of `remappedId` on the one row where `id` equals `value`, as `[value, remapped]`,
|
|
1457
|
-
* or `null` when no row matches.
|
|
1455
|
+
* or `null` when no row matches. For a numeric field the server reads the leading number of
|
|
1456
|
+
* `value` and ignores any text after it, refusing only a `value` that has none.
|
|
1458
1457
|
*/
|
|
1459
1458
|
async function remapping(id, remappedId, params, options = {}) {
|
|
1460
1459
|
await transport.require("field.remapping", options);
|
|
1461
|
-
|
|
1460
|
+
const { features } = await transport.server(options);
|
|
1461
|
+
return fetchOptionalParsed(transport, `/api/field/${id}/remapping/${remappedId}`, fieldRemappedValueSchema(features, id === remappedId), {
|
|
1462
1462
|
...options,
|
|
1463
1463
|
query: { value: params.value }
|
|
1464
1464
|
});
|
|
@@ -1481,6 +1481,7 @@ function fieldResource(transport) {
|
|
|
1481
1481
|
return {
|
|
1482
1482
|
get,
|
|
1483
1483
|
update,
|
|
1484
|
+
setDataSensitivity,
|
|
1484
1485
|
search,
|
|
1485
1486
|
remapping,
|
|
1486
1487
|
summary,
|
|
@@ -1512,6 +1513,7 @@ const SyncStashStarted = z.object({
|
|
|
1512
1513
|
task_id: z.number().int().positive()
|
|
1513
1514
|
});
|
|
1514
1515
|
const RemoteSyncSetting = z.string().nullable();
|
|
1516
|
+
const RemoteSyncBranchProperty = z.object({ "remote-sync-branch": z.string().nullable().optional() });
|
|
1515
1517
|
const FORBIDDEN_STATUS = 403;
|
|
1516
1518
|
const UNREGISTERED_STATUS = 404;
|
|
1517
1519
|
function isRemoteUnreadable(error) {
|
|
@@ -1559,16 +1561,24 @@ function gitSyncResource(transport) {
|
|
|
1559
1561
|
/**
|
|
1560
1562
|
* Import content from the remote into Metabase. The endpoint queues a task and returns at once;
|
|
1561
1563
|
* pass `wait` to poll that task until it reaches a terminal status. A server already up to date
|
|
1562
|
-
* answers no task id, and there is then nothing to poll.
|
|
1564
|
+
* answers no task id, and there is then nothing to poll. A server that guards the tracked branch
|
|
1565
|
+
* refuses with 409 when `expected_branch` disagrees with the setting; left out, it is the tracked
|
|
1566
|
+
* branch as read just before the request. `merge` folds the remote's changes into local content
|
|
1567
|
+
* by a three-way merge and keeps un-pushed local changes, where a plain import refuses on a dirty
|
|
1568
|
+
* instance.
|
|
1563
1569
|
*/
|
|
1564
1570
|
async function importFromRemote(params = {}, options = {}) {
|
|
1565
1571
|
await transport.require("gitSync.import", options);
|
|
1572
|
+
await requireMerge(params.merge, options);
|
|
1573
|
+
const expectedBranch = await guardedBranch(params.expected_branch, options);
|
|
1566
1574
|
const started = await transport.requestParsed(SyncImportStarted, "/api/ee/remote-sync/import", {
|
|
1567
1575
|
...options,
|
|
1568
1576
|
method: "POST",
|
|
1569
1577
|
body: {
|
|
1570
1578
|
branch: params.branch,
|
|
1571
|
-
force: params.force
|
|
1579
|
+
force: params.force,
|
|
1580
|
+
merge: params.merge,
|
|
1581
|
+
expected_branch: expectedBranch
|
|
1572
1582
|
}
|
|
1573
1583
|
});
|
|
1574
1584
|
const message = started.message ?? null;
|
|
@@ -1582,19 +1592,36 @@ function gitSyncResource(transport) {
|
|
|
1582
1592
|
final: await settle(params.wait, options)
|
|
1583
1593
|
};
|
|
1584
1594
|
}
|
|
1595
|
+
async function requireMerge(merge, options) {
|
|
1596
|
+
if (merge === true) await transport.requireFeatures(["remoteSyncMerge"], options);
|
|
1597
|
+
}
|
|
1598
|
+
async function guardedBranch(given, options) {
|
|
1599
|
+
if (given !== void 0) return given;
|
|
1600
|
+
const { features } = await transport.server(options);
|
|
1601
|
+
if (!features.remoteSyncBranchGuard) return;
|
|
1602
|
+
return trackedBranch(options);
|
|
1603
|
+
}
|
|
1585
1604
|
/**
|
|
1586
1605
|
* Export Metabase's content to the remote. The endpoint queues a task and returns at once; pass
|
|
1587
|
-
* `wait` to poll that task until it reaches a terminal status.
|
|
1606
|
+
* `wait` to poll that task until it reaches a terminal status. A server that guards the tracked
|
|
1607
|
+
* branch refuses with 409 when `branch` is not the tracked one; left out, it is the tracked branch
|
|
1608
|
+
* as read just before the request there, and the server's own default elsewhere. When the remote
|
|
1609
|
+
* has moved past the last sync, a plain export ends in a `conflict` task where `merge` is
|
|
1610
|
+
* available, and is refused with 400 before any task elsewhere; `merge` folds the remote's changes
|
|
1611
|
+
* in by a three-way merge instead, and `force` overwrites them.
|
|
1588
1612
|
*/
|
|
1589
1613
|
async function exportToRemote(params = {}, options = {}) {
|
|
1590
1614
|
await transport.require("gitSync.export", options);
|
|
1615
|
+
await requireMerge(params.merge, options);
|
|
1616
|
+
const branchName = await guardedBranch(params.branch, options);
|
|
1591
1617
|
const started = await transport.requestParsed(SyncExportStarted, "/api/ee/remote-sync/export", {
|
|
1592
1618
|
...options,
|
|
1593
1619
|
method: "POST",
|
|
1594
1620
|
body: {
|
|
1595
|
-
branch:
|
|
1621
|
+
branch: branchName,
|
|
1596
1622
|
message: params.message,
|
|
1597
|
-
force: params.force
|
|
1623
|
+
force: params.force,
|
|
1624
|
+
merge: params.merge
|
|
1598
1625
|
}
|
|
1599
1626
|
});
|
|
1600
1627
|
if (params.wait === void 0) return {
|
|
@@ -1679,7 +1706,7 @@ function gitSyncResource(transport) {
|
|
|
1679
1706
|
async function syncedCollections(options = {}) {
|
|
1680
1707
|
await transport.require("gitSync.syncedCollections", options);
|
|
1681
1708
|
return {
|
|
1682
|
-
data: (await
|
|
1709
|
+
data: (await listCollectionsAs(transport, SyncScopeCollection, options)).filter((entry) => entry.is_remote_synced === true),
|
|
1683
1710
|
total: null
|
|
1684
1711
|
};
|
|
1685
1712
|
}
|
|
@@ -1695,17 +1722,22 @@ function gitSyncResource(transport) {
|
|
|
1695
1722
|
}
|
|
1696
1723
|
}
|
|
1697
1724
|
/**
|
|
1698
|
-
* The branch git-sync tracks, or null when none is configured
|
|
1699
|
-
* the server has no remote-sync module
|
|
1725
|
+
* The branch git-sync tracks, or null when none is configured. Refuses when the caller may not
|
|
1726
|
+
* read the setting (it is admin-only) or the server has no remote-sync module, rather than
|
|
1727
|
+
* reading either as unset.
|
|
1700
1728
|
*/
|
|
1701
1729
|
async function branch(options = {}) {
|
|
1702
1730
|
await transport.require("gitSync.branch", options);
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1731
|
+
const tracked = (await transport.requestParsed(RemoteSyncBranchProperty, PROBE_PATH, { ...options }))["remote-sync-branch"];
|
|
1732
|
+
if (tracked === void 0) throw new ConfigError("the remote-sync-branch setting is not readable: it is visible to admins only, and absent on a server without the remote-sync module");
|
|
1733
|
+
return tracked;
|
|
1734
|
+
}
|
|
1735
|
+
/** The branch git-sync tracks, refused when none is configured or the caller may not read it. */
|
|
1736
|
+
async function trackedBranch(options = {}) {
|
|
1737
|
+
await transport.require("gitSync.trackedBranch", options);
|
|
1738
|
+
const tracked = await branch(options);
|
|
1739
|
+
if (tracked === null) throw new ConfigError("git-sync tracks no branch: the remote-sync-branch setting is unset");
|
|
1740
|
+
return tracked;
|
|
1709
1741
|
}
|
|
1710
1742
|
/**
|
|
1711
1743
|
* Poll the current task until it reaches a terminal status. A server with no task at all
|
|
@@ -1737,36 +1769,11 @@ function gitSyncResource(transport) {
|
|
|
1737
1769
|
syncedCollections,
|
|
1738
1770
|
remoteUrl,
|
|
1739
1771
|
branch,
|
|
1772
|
+
trackedBranch,
|
|
1740
1773
|
waitForTask
|
|
1741
1774
|
};
|
|
1742
1775
|
}
|
|
1743
1776
|
//#endregion
|
|
1744
|
-
//#region ../client/src/domain/glossary.ts
|
|
1745
|
-
const GlossaryCreator = z.object({
|
|
1746
|
-
id: z.number().int(),
|
|
1747
|
-
email: z.string(),
|
|
1748
|
-
first_name: z.string().nullable(),
|
|
1749
|
-
last_name: z.string().nullable()
|
|
1750
|
-
}).loose();
|
|
1751
|
-
const Glossary = z.object({
|
|
1752
|
-
id: z.number().int(),
|
|
1753
|
-
term: z.string(),
|
|
1754
|
-
definition: z.string(),
|
|
1755
|
-
creator_id: z.number().int(),
|
|
1756
|
-
creator: GlossaryCreator,
|
|
1757
|
-
created_at: z.string(),
|
|
1758
|
-
updated_at: z.string()
|
|
1759
|
-
}).loose();
|
|
1760
|
-
Glossary.pick({
|
|
1761
|
-
id: true,
|
|
1762
|
-
term: true,
|
|
1763
|
-
definition: true
|
|
1764
|
-
}).strip();
|
|
1765
|
-
z.object({
|
|
1766
|
-
term: z.string().min(1),
|
|
1767
|
-
definition: z.string().min(1)
|
|
1768
|
-
}).strict();
|
|
1769
|
-
//#endregion
|
|
1770
1777
|
//#region ../client/src/resources/glossary.ts
|
|
1771
1778
|
const GlossaryApiList = z.object({ data: z.array(Glossary) }).loose();
|
|
1772
1779
|
function glossaryResource(transport) {
|
|
@@ -1819,6 +1826,17 @@ function glossaryResource(transport) {
|
|
|
1819
1826
|
};
|
|
1820
1827
|
}
|
|
1821
1828
|
//#endregion
|
|
1829
|
+
//#region ../client/src/resources/request-body.ts
|
|
1830
|
+
/**
|
|
1831
|
+
* Parse the body a caller hands a method, refusing one that does not match `schema` before any
|
|
1832
|
+
* request. `what` names the body in the refusal.
|
|
1833
|
+
*/
|
|
1834
|
+
function parseRequestBody(schema, value, what) {
|
|
1835
|
+
const parsed = schema.safeParse(value);
|
|
1836
|
+
if (!parsed.success) throw new ConfigError(`invalid ${what}: ${parsed.error.issues.map(formatZodIssue).join("; ")}`);
|
|
1837
|
+
return parsed.data;
|
|
1838
|
+
}
|
|
1839
|
+
//#endregion
|
|
1822
1840
|
//#region ../client/src/resources/library.ts
|
|
1823
1841
|
const LIBRARY_ROOT_PATH = "/api/ee/library/";
|
|
1824
1842
|
const PUBLISH_TABLES_PATH = "/api/ee/data-studio/table/publish-tables";
|
|
@@ -1835,7 +1853,7 @@ function libraryResource(transport) {
|
|
|
1835
1853
|
return toLibrary(wire, await libraryListing(options));
|
|
1836
1854
|
}
|
|
1837
1855
|
async function libraryListing(options) {
|
|
1838
|
-
const data = await
|
|
1856
|
+
const data = await listCollectionsAs(transport, LibraryCollectionInfo, options);
|
|
1839
1857
|
const byId = /* @__PURE__ */ new Map();
|
|
1840
1858
|
for (const collection of data) if (typeof collection.id === "number") byId.set(collection.id, collection);
|
|
1841
1859
|
return byId;
|
|
@@ -1868,26 +1886,31 @@ function libraryResource(transport) {
|
|
|
1868
1886
|
}
|
|
1869
1887
|
/**
|
|
1870
1888
|
* Publish tables — and every upstream table they depend on — into a collection, so they lead the
|
|
1871
|
-
* data pickers and rank up in search. Answers the collection they landed in.
|
|
1889
|
+
* data pickers and rank up in search. Answers the collection they landed in. The endpoint
|
|
1890
|
+
* answers the same whether or not the selectors matched a table, so a body that does not match
|
|
1891
|
+
* `LibraryPublishTablesInput` is refused before any request.
|
|
1872
1892
|
*/
|
|
1873
1893
|
async function publishTables(params, options = {}) {
|
|
1874
1894
|
await transport.require("library.publishTables", options);
|
|
1895
|
+
const body = parseRequestBody(LibraryPublishTablesInput, params, "tables to publish");
|
|
1875
1896
|
return (await transport.requestParsed(PublishTablesResponse, PUBLISH_TABLES_PATH, {
|
|
1876
1897
|
...options,
|
|
1877
1898
|
method: "POST",
|
|
1878
|
-
body
|
|
1899
|
+
body
|
|
1879
1900
|
})).target_collection;
|
|
1880
1901
|
}
|
|
1881
1902
|
/**
|
|
1882
1903
|
* Clear the Library collection from tables, and recursively from every downstream table that
|
|
1883
|
-
* depends on them. The endpoint answers no JSON body
|
|
1904
|
+
* depends on them. The endpoint answers no JSON body, whether or not the selectors matched a
|
|
1905
|
+
* table, so selectors that do not match `TableSelectors` are refused before any request.
|
|
1884
1906
|
*/
|
|
1885
1907
|
async function unpublishTables(params, options = {}) {
|
|
1886
1908
|
await transport.require("library.unpublishTables", options);
|
|
1909
|
+
const body = parseRequestBody(TableSelectors, params, "table selectors");
|
|
1887
1910
|
await transport.requestRaw(UNPUBLISH_TABLES_PATH, {
|
|
1888
1911
|
...options,
|
|
1889
1912
|
method: "POST",
|
|
1890
|
-
body
|
|
1913
|
+
body,
|
|
1891
1914
|
expectContentType: "binary"
|
|
1892
1915
|
});
|
|
1893
1916
|
}
|
|
@@ -2140,48 +2163,21 @@ function metricResource(transport) {
|
|
|
2140
2163
|
};
|
|
2141
2164
|
}
|
|
2142
2165
|
//#endregion
|
|
2143
|
-
//#region ../client/src/domain/moderation-review.ts
|
|
2144
|
-
const ModeratedItemType = z.enum(["card", "dashboard"]);
|
|
2145
|
-
const ModerationStatus = z.enum(["verified"]);
|
|
2146
|
-
const ModerationReview = z.object({
|
|
2147
|
-
id: z.number().int(),
|
|
2148
|
-
moderated_item_id: z.number().int(),
|
|
2149
|
-
moderated_item_type: ModeratedItemType,
|
|
2150
|
-
moderator_id: z.number().int(),
|
|
2151
|
-
status: ModerationStatus.nullable(),
|
|
2152
|
-
text: z.string().nullable(),
|
|
2153
|
-
most_recent: z.boolean(),
|
|
2154
|
-
created_at: z.string(),
|
|
2155
|
-
updated_at: z.string()
|
|
2156
|
-
}).loose();
|
|
2157
|
-
ModerationReview.pick({
|
|
2158
|
-
id: true,
|
|
2159
|
-
moderated_item_id: true,
|
|
2160
|
-
moderated_item_type: true,
|
|
2161
|
-
status: true,
|
|
2162
|
-
text: true,
|
|
2163
|
-
most_recent: true
|
|
2164
|
-
}).strip();
|
|
2165
|
-
z.object({
|
|
2166
|
-
moderated_item_id: z.number().int().positive(),
|
|
2167
|
-
moderated_item_type: ModeratedItemType,
|
|
2168
|
-
status: ModerationStatus.nullable().optional(),
|
|
2169
|
-
text: z.string().nullable().optional()
|
|
2170
|
-
}).strict();
|
|
2171
|
-
//#endregion
|
|
2172
2166
|
//#region ../client/src/resources/moderation-review.ts
|
|
2173
2167
|
function moderationReviewResource(transport) {
|
|
2174
2168
|
/**
|
|
2175
2169
|
* Create a moderation review on a card or dashboard. `status: "verified"` marks the item
|
|
2176
2170
|
* verified, `null` or an absent status records a note that leaves it unverified. The new review
|
|
2177
2171
|
* becomes the item's most recent one; the server keeps the ten newest per item. Admins only.
|
|
2172
|
+
* A body that does not match `ModerationReviewCreateInput` is refused before any request.
|
|
2178
2173
|
*/
|
|
2179
2174
|
async function create(params, options = {}) {
|
|
2180
2175
|
await transport.require("moderationReview.create", options);
|
|
2176
|
+
const body = parseRequestBody(ModerationReviewCreateInput, params, "moderation review");
|
|
2181
2177
|
return transport.requestParsed(ModerationReview, "/api/moderation-review", {
|
|
2182
2178
|
...options,
|
|
2183
2179
|
method: "POST",
|
|
2184
|
-
body
|
|
2180
|
+
body
|
|
2185
2181
|
});
|
|
2186
2182
|
}
|
|
2187
2183
|
return { create };
|
|
@@ -2702,8 +2698,10 @@ function searchResource(transport) {
|
|
|
2702
2698
|
* may match, `archived` swaps the active set for the archived one, `table_db_id` restricts to
|
|
2703
2699
|
* items on one database, `verified` to verified content, `collection` to one collection and its
|
|
2704
2700
|
* descendants, `created_by` to items created by any of those users, `search_native_query` also
|
|
2705
|
-
* matches
|
|
2706
|
-
*
|
|
2701
|
+
* matches native query text but narrows to the models that carry one (cards, models, metrics,
|
|
2702
|
+
* actions, transforms), `include_metadata` attaches each card's `result_metadata`,
|
|
2703
|
+
* `include_dashboard_questions` also matches questions saved into a dashboard (excluded by
|
|
2704
|
+
* default), and `limit`/`offset` are the window the server applies before ranking hydration.
|
|
2707
2705
|
*/
|
|
2708
2706
|
async function query(params = {}, options = {}) {
|
|
2709
2707
|
await transport.require("search.query", options);
|
|
@@ -2720,7 +2718,8 @@ function searchResource(transport) {
|
|
|
2720
2718
|
collection: params.collection,
|
|
2721
2719
|
created_by: params.created_by,
|
|
2722
2720
|
search_native_query: params.search_native_query,
|
|
2723
|
-
include_metadata: params.include_metadata
|
|
2721
|
+
include_metadata: params.include_metadata,
|
|
2722
|
+
include_dashboard_questions: params.include_dashboard_questions
|
|
2724
2723
|
}
|
|
2725
2724
|
});
|
|
2726
2725
|
return {
|
|
@@ -2904,14 +2903,18 @@ function snippetResource(transport) {
|
|
|
2904
2903
|
const TableApiList = z.array(Table);
|
|
2905
2904
|
const TableApiFks = z.array(TableForeignKey);
|
|
2906
2905
|
const SyncSchemaResponse = z.object({ status: z.literal("ok") });
|
|
2907
|
-
const
|
|
2906
|
+
const FieldValuesResponse = z.object({ status: z.literal("success") });
|
|
2908
2907
|
const BulkEditResponse = z.object({});
|
|
2909
2908
|
const BULK_EDIT_PATH = "/api/data-studio/table/edit";
|
|
2909
|
+
const BULK_SYNC_SCHEMA_PATH = "/api/data-studio/table/sync-schema";
|
|
2910
|
+
const BULK_RESCAN_VALUES_PATH = "/api/data-studio/table/rescan-values";
|
|
2911
|
+
const BULK_DISCARD_VALUES_PATH = "/api/data-studio/table/discard-values";
|
|
2910
2912
|
const LIST_PARAM_FEATURES = [
|
|
2911
2913
|
["can-query", "tableListAccessFilters"],
|
|
2912
2914
|
["can-write", "tableListAccessFilters"],
|
|
2913
2915
|
["include-transform-targets", "tableListTransformTargets"],
|
|
2914
|
-
["unused-only", "tableUnusedFilter"]
|
|
2916
|
+
["unused-only", "tableUnusedFilter"],
|
|
2917
|
+
["published-only", "tableListPublishedFilter"]
|
|
2915
2918
|
];
|
|
2916
2919
|
function listParamFeatures(params) {
|
|
2917
2920
|
return LIST_PARAM_FEATURES.filter(([param]) => params[param] !== void 0).map(([, feature]) => feature);
|
|
@@ -2925,7 +2928,7 @@ function tableResource(transport) {
|
|
|
2925
2928
|
* List every table the caller can see, across all databases. `term` matches names and display
|
|
2926
2929
|
* names; `can-query` and `can-write` keep only the tables the caller may query or edit the
|
|
2927
2930
|
* metadata of; `include-transform-targets` adds tables a transform writes to; `unused-only` keeps
|
|
2928
|
-
* tables nothing depends on.
|
|
2931
|
+
* tables nothing depends on; `published-only` keeps tables published to the library.
|
|
2929
2932
|
*/
|
|
2930
2933
|
async function list(params = {}, options = {}) {
|
|
2931
2934
|
await transport.require("table.list", options);
|
|
@@ -2943,6 +2946,7 @@ function tableResource(transport) {
|
|
|
2943
2946
|
"owner-email": params["owner-email"],
|
|
2944
2947
|
"orphan-only": params["orphan-only"],
|
|
2945
2948
|
"unused-only": params["unused-only"],
|
|
2949
|
+
"published-only": params["published-only"],
|
|
2946
2950
|
"can-query": params["can-query"],
|
|
2947
2951
|
"can-write": params["can-write"],
|
|
2948
2952
|
"include-transform-targets": params["include-transform-targets"]
|
|
@@ -2992,38 +2996,107 @@ function tableResource(transport) {
|
|
|
2992
2996
|
};
|
|
2993
2997
|
}
|
|
2994
2998
|
/**
|
|
2995
|
-
* Trigger a
|
|
2996
|
-
*
|
|
2999
|
+
* Trigger a sync of this table: its columns, their fingerprints and its cached field values. It
|
|
3000
|
+
* never discovers new tables. The sync runs after the call returns; a warehouse the server cannot
|
|
3001
|
+
* connect to is a 422.
|
|
2997
3002
|
*/
|
|
2998
3003
|
async function syncSchema(id, options = {}) {
|
|
2999
3004
|
await transport.require("table.syncSchema", options);
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3005
|
+
return {
|
|
3006
|
+
id,
|
|
3007
|
+
status: (await transport.requestParsed(SyncSchemaResponse, `/api/table/${id}/sync_schema`, {
|
|
3008
|
+
...options,
|
|
3009
|
+
method: "POST"
|
|
3010
|
+
})).status
|
|
3011
|
+
};
|
|
3004
3012
|
}
|
|
3005
3013
|
/**
|
|
3006
|
-
* Trigger an update of the field values of every eligible field of this table
|
|
3007
|
-
* after the call returns.
|
|
3014
|
+
* Trigger an update of the field values of every eligible field of this table that already has a
|
|
3015
|
+
* cached set. The scan runs after the call returns.
|
|
3008
3016
|
*/
|
|
3009
3017
|
async function rescanValues(id, options = {}) {
|
|
3010
3018
|
await transport.require("table.rescanValues", options);
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3019
|
+
return {
|
|
3020
|
+
id,
|
|
3021
|
+
status: (await transport.requestParsed(FieldValuesResponse, `/api/table/${id}/rescan_values`, {
|
|
3022
|
+
...options,
|
|
3023
|
+
method: "POST"
|
|
3024
|
+
})).status
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Discard the cached field values of every field of this table, custom display values included.
|
|
3029
|
+
* No scan recreates a discarded set; the server rebuilds it, without the display values, the next
|
|
3030
|
+
* time the field's values are read.
|
|
3031
|
+
*/
|
|
3032
|
+
async function discardValues(id, options = {}) {
|
|
3033
|
+
await transport.require("table.discardValues", options);
|
|
3034
|
+
return {
|
|
3035
|
+
id,
|
|
3036
|
+
status: (await transport.requestParsed(FieldValuesResponse, `/api/table/${id}/discard_values`, {
|
|
3037
|
+
...options,
|
|
3038
|
+
method: "POST"
|
|
3039
|
+
})).status
|
|
3040
|
+
};
|
|
3015
3041
|
}
|
|
3016
3042
|
/**
|
|
3017
3043
|
* Set the same metadata on every table the selectors pick out. A table leaving the `hidden` data
|
|
3018
|
-
* layer is re-synced after the call returns.
|
|
3044
|
+
* layer is re-synced after the call returns. The server answers the same whether or not the
|
|
3045
|
+
* selectors matched a table.
|
|
3019
3046
|
*/
|
|
3020
3047
|
async function bulkEdit(params, options = {}) {
|
|
3021
3048
|
await transport.require("table.bulkEdit", options);
|
|
3049
|
+
await requireDataAuthorityNull(params.data_authority, options);
|
|
3022
3050
|
await transport.requestParsed(BulkEditResponse, BULK_EDIT_PATH, {
|
|
3023
3051
|
...options,
|
|
3024
3052
|
method: "POST",
|
|
3025
3053
|
body: params
|
|
3026
3054
|
});
|
|
3055
|
+
return {
|
|
3056
|
+
accepted: true,
|
|
3057
|
+
...params
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
async function requireDataAuthorityNull(value, options) {
|
|
3061
|
+
if (value === null) await transport.requireFeatures(["tableUserValueWithdrawal"], options);
|
|
3062
|
+
}
|
|
3063
|
+
async function postSelection(path, selectors, options) {
|
|
3064
|
+
const body = parseRequestBody(TableSelectors, selectors, "table selectors");
|
|
3065
|
+
await transport.requestRaw(path, {
|
|
3066
|
+
...options,
|
|
3067
|
+
method: "POST",
|
|
3068
|
+
body,
|
|
3069
|
+
expectContentType: "binary"
|
|
3070
|
+
});
|
|
3071
|
+
return {
|
|
3072
|
+
accepted: true,
|
|
3073
|
+
...body
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Trigger a sync of every table the selectors pick out: its columns, their fingerprints and its
|
|
3078
|
+
* cached field values. Every database behind them must answer a connection test first, or the
|
|
3079
|
+
* call is a 422; the syncs run after it returns.
|
|
3080
|
+
*/
|
|
3081
|
+
async function bulkSyncSchema(selectors, options = {}) {
|
|
3082
|
+
await transport.require("table.bulkSyncSchema", options);
|
|
3083
|
+
return postSelection(BULK_SYNC_SCHEMA_PATH, selectors, options);
|
|
3084
|
+
}
|
|
3085
|
+
/**
|
|
3086
|
+
* Trigger a field-values rescan of every table the selectors pick out, refreshing the sets that
|
|
3087
|
+
* are already cached. The scans run after the call returns.
|
|
3088
|
+
*/
|
|
3089
|
+
async function bulkRescanValues(selectors, options = {}) {
|
|
3090
|
+
await transport.require("table.bulkRescanValues", options);
|
|
3091
|
+
return postSelection(BULK_RESCAN_VALUES_PATH, selectors, options);
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Discard the cached field values of every table the selectors pick out, custom display values
|
|
3095
|
+
* included. No scan recreates a discarded set.
|
|
3096
|
+
*/
|
|
3097
|
+
async function bulkDiscardValues(selectors, options = {}) {
|
|
3098
|
+
await transport.require("table.bulkDiscardValues", options);
|
|
3099
|
+
return postSelection(BULK_DISCARD_VALUES_PATH, selectors, options);
|
|
3027
3100
|
}
|
|
3028
3101
|
async function updateFromCsv(id, action, file, options) {
|
|
3029
3102
|
await transport.requestRaw(`/api/table/${id}/${UPLOAD_UPDATE_PATHS[action]}`, {
|
|
@@ -3065,7 +3138,11 @@ function tableResource(transport) {
|
|
|
3065
3138
|
fks,
|
|
3066
3139
|
syncSchema,
|
|
3067
3140
|
rescanValues,
|
|
3141
|
+
discardValues,
|
|
3068
3142
|
bulkEdit,
|
|
3143
|
+
bulkSyncSchema,
|
|
3144
|
+
bulkRescanValues,
|
|
3145
|
+
bulkDiscardValues,
|
|
3069
3146
|
appendCsv,
|
|
3070
3147
|
replaceCsv
|
|
3071
3148
|
};
|
|
@@ -4207,6 +4284,7 @@ function createClient(config, options) {
|
|
|
4207
4284
|
collection: collectionResource(transport),
|
|
4208
4285
|
contentTranslation: contentTranslationResource(transport),
|
|
4209
4286
|
dashboard: dashboardResource(transport),
|
|
4287
|
+
dataAction: dataActionResource(transport),
|
|
4210
4288
|
database: databaseResource(transport),
|
|
4211
4289
|
dataset: datasetResource(transport),
|
|
4212
4290
|
dependency: dependencyResource(transport),
|