@metabase/cli 0.3.2 → 0.4.0
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-CC6KSwjX.mjs} +5 -5
- package/dist/{alert-DCLhfwdv.mjs → alert-Dt6La9tK.mjs} +7 -7
- package/dist/{alerts-DRin_wt2.mjs → alerts-ClKnJqgB.mjs} +6 -6
- package/dist/{append-DQ9rPJHZ.mjs → append-pnaQWP_A.mjs} +4 -4
- package/dist/{archive-D6xzHaM3.mjs → archive-By1pLYtO.mjs} +3 -3
- package/dist/{archive-xcgoVPwv.mjs → archive-CLu2TGW5.mjs} +5 -5
- package/dist/{archive-HeRygdKz2.mjs → archive-COP9joWU.mjs} +4 -4
- package/dist/{archive-COFQAHAL.mjs → archive-CSnBFcQ_.mjs} +3 -3
- package/dist/{archive-1YVo-Wsu.mjs → archive-Ct1eyolN.mjs} +3 -3
- package/dist/{archive-_c-ISZmi.mjs → archive-D7nAQcCz.mjs} +3 -3
- package/dist/{archive-BzVxRqpL.mjs → archive-DEDA48w3.mjs} +5 -5
- package/dist/{archive-BVRKE9Ev.mjs → archive-DJAsSzCz.mjs} +5 -5
- package/dist/{archive-BPCgmLcV.mjs → archive-DtabbPUk.mjs} +4 -4
- package/dist/{archive-o5cWV3vZ.mjs → archive-YNpa8daf.mjs} +3 -3
- package/dist/{archive-D3yPvUtz.mjs → archive-ewitrKdx.mjs} +5 -5
- package/dist/{auth-DJn5T6zA.mjs → auth-DdLhXCn-.mjs} +5 -5
- package/dist/body-Dd-TwYYL.mjs +17 -0
- package/dist/branch-flag-pFQPNYKr.mjs +9 -0
- package/dist/{branches-CUyPxeeW.mjs → branches-ZvGNhed6.mjs} +3 -3
- package/dist/breaking-BLswgvkA.mjs +36 -0
- package/dist/broken-BN0nL2hf.mjs +37 -0
- package/dist/bulk-discard-values-DFJUjSnE.mjs +49 -0
- package/dist/bulk-edit-Brqr67bu.mjs +53 -0
- package/dist/bulk-rescan-values-DndXXi2N.mjs +28 -0
- package/dist/bulk-sync-schema-mO-t2QlL.mjs +28 -0
- package/dist/{cancel-BNuVls58.mjs → cancel-DP03dXBf.mjs} +3 -3
- package/dist/{cancel-task-DUmlQQpi.mjs → cancel-task-CELBfBPP.mjs} +4 -4
- package/dist/{card-voh1k4hl.mjs → card-Bv4ZN0oV.mjs} +5 -3
- package/dist/card-CFd-GUEM.mjs +25 -0
- package/dist/{card-CEkp1mcI.mjs → card-DSrgU7lT.mjs} +1 -1
- package/dist/{cards-_gbvw3wp.mjs → cards-Cn2ywFTJ.mjs} +6 -6
- package/dist/cli.mjs +410 -100
- package/dist/{client-BnK0evYf.mjs → client-ToLiPu9q.mjs} +316 -316
- package/dist/{collection-DYM0p3Xl.mjs → collection-BG3Ksea-.mjs} +1 -1
- package/dist/collection-BKNShKcY.mjs +21 -0
- package/dist/{collection-BxdPxD38.mjs → collection-D3KXhvnc.mjs} +7 -5
- package/dist/{collection-namespace-DM90lA8C.mjs → collection-namespace-CWW6hZxK.mjs} +2 -2
- package/dist/{content-translation-CqB3peU9.mjs → content-translation-C19SqZWp.mjs} +3 -3
- package/dist/copy-BGK8Wz6d.mjs +55 -0
- package/dist/copy-COLUuiuF.mjs +36 -0
- package/dist/copy-flags-eU8aa0zj.mjs +32 -0
- package/dist/{create-CnJKj9Nl.mjs → create-B2tuInV9.mjs} +4 -4
- package/dist/{create-D4Y69cDF.mjs → create-B3TKri1E.mjs} +4 -4
- package/dist/{create-BSvTs-EV.mjs → create-B4gXKDRr.mjs} +3 -3
- package/dist/create-B63JphYe.mjs +34 -0
- package/dist/{create-IFjwHs0G.mjs → create-BH6kLjHS.mjs} +4 -4
- package/dist/{create-BIUVvIGH.mjs → create-BwifyhyL.mjs} +3 -3
- package/dist/{create-CwXUMOMd.mjs → create-Colz5bOO.mjs} +3 -3
- package/dist/{create-Cm9Z-rfe2.mjs → create-CulUZgN1.mjs} +4 -4
- package/dist/{create-DNx9TGHs.mjs → create-Cxuqr3kT.mjs} +6 -6
- package/dist/{create-CUHpxANR.mjs → create-CzW_UTE7.mjs} +6 -6
- package/dist/{create-BMKuihoI.mjs → create-DNR8RMvV.mjs} +6 -6
- package/dist/{create-DMVw9nrZ.mjs → create-DSHeoV7e.mjs} +4 -4
- package/dist/{create-DVo8-IzZ.mjs → create-DWbW2WSc.mjs} +6 -6
- package/dist/{create-va8bByVt.mjs → create-Dx8nfjGs.mjs} +3 -3
- package/dist/{create-B7S5fCkD.mjs → create-XGomrTz5.mjs} +5 -5
- package/dist/{create-branch-Cw-uXows.mjs → create-branch-DxL7KUZp.mjs} +4 -4
- package/dist/{create-B48rmY8v.mjs → create-g1f2yJ4s.mjs} +3 -3
- package/dist/{csv-CaKx1oFZ.mjs → csv-C6TEfLMi.mjs} +4 -4
- package/dist/{current-task-lGh69Z1i.mjs → current-task-CHs0zNFM.mjs} +4 -4
- package/dist/dashboard-AWrXqQ7a.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/database-D-CRyRIv.mjs +45 -0
- package/dist/{database-C3E9PZSx.mjs → database-MlUPpitM.mjs} +1 -1
- package/dist/dataset-p5oNPQgL.mjs +66 -0
- package/dist/{db-BRHPjshe.mjs → db-BFSeETMO.mjs} +7 -7
- package/dist/{delete-DMETa-37.mjs → delete-BUKgSJhh.mjs} +4 -4
- package/dist/{delete-CQWCfqHf.mjs → delete-CPBByycV.mjs} +4 -4
- package/dist/{delete-Ci0aDYpf.mjs → delete-Cucqn4-V.mjs} +4 -4
- package/dist/{delete-BxBadE3q.mjs → delete-D79TlpcE.mjs} +4 -4
- package/dist/delete-DZJxBmdU.mjs +44 -0
- package/dist/{delete-G6EiGn2Q.mjs → delete-DndykJn2.mjs} +4 -4
- package/dist/delete-runtime-BbmRg_in.mjs +55 -0
- package/dist/{delete-table-N4rZtt1T.mjs → delete-table-CbsWcjh5.mjs} +4 -4
- package/dist/{dependencies-edN0P1SS.mjs → dependencies-B-880phi.mjs} +5 -5
- package/dist/dependency-DBUJwXqv.mjs +15 -0
- package/dist/dependency-DKSjKT8P.mjs +165 -0
- package/dist/dependency-DSxKm9oS.mjs +111 -0
- package/dist/dependents-C_FDnpZs.mjs +52 -0
- package/dist/{dirty-U51bMoCP.mjs → dirty-B-Is68--.mjs} +5 -5
- package/dist/discard-values-yzH-kIsr.mjs +55 -0
- package/dist/document-BRaba87v.mjs +20 -0
- package/dist/{document-CA0Q6lqu.mjs → document-C18b5rM6.mjs} +1 -1
- package/dist/{document-BHpLJbKU.mjs → document-DFCj1Az_.mjs} +2 -1
- package/dist/{download-BJA6k-e6.mjs → download-DluF-vnU.mjs} +2 -2
- package/dist/{eid-BtlRU1E0.mjs → eid-Dz-mP40j.mjs} +11 -10
- package/dist/entity-CA4zfRt4.mjs +20 -0
- package/dist/entry-flags-7x7bIyOQ.mjs +42 -0
- package/dist/{events-B5rnOo-L.mjs → events-2sOk6H09.mjs} +4 -4
- package/dist/export-BKkAJOFb.mjs +74 -0
- package/dist/export-flags-NiZ7C3Gm.mjs +81 -0
- package/dist/export-preflight-CwJ_3-iX.mjs +35 -0
- package/dist/{field-CcN4oZy6.mjs → field-5nivEfd6.mjs} +33 -3
- package/dist/field-BARgq5I9.mjs +21 -0
- package/dist/field-wmN6raOG.mjs +128 -0
- package/dist/{fields-zQ6O_W_H.mjs → fields-Bod0s_uV.mjs} +6 -6
- package/dist/filter-flags-BYcbB85j.mjs +71 -0
- package/dist/fks-IUw66K_Q.mjs +36 -0
- package/dist/{get-BDrmBZ1z.mjs → get-B8DUMrCw.mjs} +5 -5
- package/dist/{get-is8x5f2n.mjs → get-BGqvoGQM.mjs} +3 -3
- package/dist/{get-CekXFP3x.mjs → get-BSUsfysk.mjs} +3 -3
- package/dist/{get-CeSQptdl.mjs → get-BXsLkoit.mjs} +5 -5
- package/dist/{get-DhpMuTSt.mjs → get-BXssHyJ1.mjs} +5 -5
- package/dist/get-Bct52yPw.mjs +36 -0
- package/dist/{get-DXwlZjw0.mjs → get-Besqwy32.mjs} +3 -3
- package/dist/{get-BLjcCXp8.mjs → get-BfSX-OeS.mjs} +3 -3
- package/dist/{get-BLcS4il2.mjs → get-Biy4gOzu2.mjs} +3 -3
- package/dist/{get-BSoMWp4t2.mjs → get-CYIeiTZ9.mjs} +4 -4
- package/dist/{get-CwiJWeH4.mjs → get-CaEiQnSw.mjs} +4 -4
- package/dist/{get-xPv7e5Ez.mjs → get-Cl81y0Md.mjs} +5 -5
- package/dist/{get-Cf6a4fFN.mjs → get-D1NjMXAH.mjs} +4 -4
- package/dist/{get-EFsmL4le.mjs → get-D2cPuOPR.mjs} +5 -5
- package/dist/{get-Dg-S07ri.mjs → get-DITlshJH.mjs} +3 -3
- package/dist/{get-CTp5l7aU.mjs → get-DLyg6Al9.mjs} +3 -3
- package/dist/{get-93wuhTn2.mjs → get-DQZfaVNq.mjs} +4 -4
- package/dist/{get-CG6G-mzV.mjs → get-DtBqoGTa.mjs} +5 -5
- package/dist/{get-DC_huYD8.mjs → get-_ik_5_lQ.mjs} +5 -5
- package/dist/{get-run-DwY4sFGy.mjs → get-run-CEc_tr5b.mjs} +4 -4
- package/dist/{git-sync-BwBRmEhE.mjs → git-sync-COokpYgc.mjs} +12 -3
- package/dist/git-sync-DKcaddkV.mjs +29 -0
- package/dist/git-sync-DspFahwV.mjs +165 -0
- package/dist/glossary-BlNCrYbw.mjs +30 -0
- package/dist/glossary-CWIX8Zh6.mjs +14 -0
- package/dist/glossary-LmZWwCNP.mjs +21 -0
- package/dist/graph-f6Bp1e8U.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-B8MmN6yh.mjs} +4 -4
- package/dist/{import-Cs7wk058.mjs → import-Bhq15KgP.mjs} +19 -8
- package/dist/{input-DEvkIjGr.mjs → input-D8qW-KtR.mjs} +6 -2
- package/dist/{is-dirty-XqDfqXGi.mjs → is-dirty-CAsVuVx8.mjs} +2 -2
- package/dist/{items-BloAjPwA.mjs → items-BZJomiDE.mjs} +8 -8
- package/dist/{key-PYetuQ13.mjs → key-BynJSK9u.mjs} +1 -1
- package/dist/{library-Dgq_5BFh.mjs → library-B7wDH-Nc.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-CZCaqPoo.mjs → list-B2uUl26x.mjs} +6 -6
- package/dist/{list-3ErmGdY0.mjs → list-B4luDSYj.mjs} +6 -6
- package/dist/{list-D04uiS3F.mjs → list-B8ND9t2h.mjs} +3 -3
- package/dist/{list-CghNKfYJ.mjs → list-BT5t8ZOl.mjs} +4 -4
- package/dist/{list-VzrtA9lt.mjs → list-BT7xiUQe.mjs} +3 -3
- package/dist/{list-D9d5ocYi.mjs → list-BWFCv_zk.mjs} +5 -5
- package/dist/{list-DboUvg-Y.mjs → list-BtZVe1Nq.mjs} +6 -6
- package/dist/{list-sdCIS2Df.mjs → list-BwdSG-P5.mjs} +5 -5
- package/dist/{list-yV6CyPzn.mjs → list-C-A-2HFq.mjs} +3 -3
- package/dist/list-C9x--9Jq.mjs +101 -0
- package/dist/{list-CUJ1wem9.mjs → list-CCdXig7b.mjs} +4 -4
- package/dist/{list-BfLo1xI8.mjs → list-CJDFoOHb.mjs} +3 -3
- package/dist/{list-Bzm5mXRo.mjs → list-CLFu3mQB.mjs} +3 -3
- package/dist/{list-BZnf3RmA.mjs → list-Cd40Kr0R.mjs} +3 -3
- package/dist/{list-CUXlZiS1.mjs → list-Cj_mTxbY.mjs} +4 -4
- package/dist/{list-f8Csdjyc.mjs → list-CtS50R7m.mjs} +5 -5
- package/dist/{list-vsXIMssK.mjs → list-CvZyTwmV.mjs} +5 -5
- package/dist/list-DcnNlYQA.mjs +35 -0
- package/dist/{list-DuJezLm_.mjs → list-DtgbtE3_.mjs} +3 -3
- package/dist/{login-Vw51Gts5.mjs → login-Bi_nGMJ9.mjs} +6 -6
- package/dist/{logout-BDIqoVhv.mjs → logout-CiHQJWTu.mjs} +2 -2
- package/dist/{measure-LY9Tp9QZ.mjs → measure-D2qq5e8f.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-CZow98nb.mjs} +3 -3
- package/dist/{parse-enum-Dc0dMZ3P.mjs → parse-enum-CLIXMsd8.mjs} +1 -1
- package/dist/parse-id-BW09NysN.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-K6LPLYPb.mjs} +4 -4
- package/dist/{poll-CZeXepUQ.mjs → poll-Dz4tUm2f.mjs} +2 -2
- package/dist/{preflight-DcULqq8E.mjs → preflight-CX6cqB90.mjs} +3 -3
- package/dist/{process-CTrfxxaC.mjs → process-D0HdqZ3r.mjs} +1 -1
- package/dist/{publish-qVFmJQ1E.mjs → publish-COatW4Un.mjs} +4 -4
- package/dist/{pulse-x0gFxWfG.mjs → pulse-D1uh8UIU.mjs} +1 -1
- package/dist/query-BJXTIDhy.mjs +328 -0
- package/dist/{query-Cq1lmqL5.mjs → query-DmvkyDfo.mjs} +14 -33
- package/dist/remapping-CPAvDKHV.mjs +53 -0
- package/dist/{remove-collection-DBqh2Lqm.mjs → remove-collection-Bg-sNX3U.mjs} +5 -5
- package/dist/{render-Gx1hR7IF.mjs → render-BSfDD6ip.mjs} +2 -2
- package/dist/{replace-CujInVY9.mjs → replace-RCHeZLUT.mjs} +4 -4
- package/dist/{rescan-values-HypqBCSK.mjs → rescan-values-CpDGYZvf.mjs} +5 -5
- package/dist/rescan-values-PeMnpaFY.mjs +32 -0
- package/dist/{run-DEkQSOQa.mjs → run-CaQ7kubO.mjs} +3 -3
- package/dist/{run-b3jyF29q.mjs → run-DkRkZRgf.mjs} +4 -4
- package/dist/{runs-GHqHLGy4.mjs → runs-BDjoVJ0P.mjs} +5 -5
- package/dist/{runtime-nCPku2nN.mjs → runtime-CZ5zh32z.mjs} +21 -82
- package/dist/{schema-tables-B5L05Y1L.mjs → schema-tables-C2qjLcPq.mjs} +6 -6
- package/dist/{schemas-Clx26p_4.mjs → schemas-D8hfNduk.mjs} +4 -4
- package/dist/search-BrQQuNmh.mjs +131 -0
- package/dist/search-CnTXKJgx.mjs +85 -0
- package/dist/{segment-DiRJcbam.mjs → segment-Bi6eqj3e.mjs} +6 -6
- package/dist/{send-DIHkDNBN.mjs → send-CAjgVNlA.mjs} +3 -3
- package/dist/{set-D77qUZML.mjs → set-BXTkYWid.mjs} +4 -4
- package/dist/{set-active-DCdFgD0O.mjs → set-active-CBQVCePU.mjs} +3 -3
- package/dist/set-sensitivity-D39kGTob.mjs +57 -0
- package/dist/{setting-DR9bj232.mjs → setting-CPkvkc4H.mjs} +4 -4
- package/dist/{setup-DGa2LLEp.mjs → setup-Be3xDXHi.mjs} +3 -3
- package/dist/{signal-k7cm5N6h.mjs → signal-CxWeLszu.mjs} +1 -1
- package/dist/{skill-list-DAvGGHzS.mjs → skill-list-CBGq30sI.mjs} +2 -2
- package/dist/{skills-CqtNuSXM.mjs → skills-CJ9eXouJ.mjs} +2 -2
- package/dist/{skills-CCn7cyMP.mjs → skills-DyiLycMY.mjs} +3 -3
- package/dist/snippet-QirK70R_.mjs +19 -0
- package/dist/{stash-BTtsV0AG.mjs → stash-BVN3s5N_.mjs} +6 -6
- package/dist/{status-CW7Dt-nV.mjs → status-BtbMmIWo.mjs} +7 -7
- package/dist/{status-XgSS3StV.mjs → status-CxP6w3aL.mjs} +3 -3
- package/dist/{subscription-CofRU47d.mjs → subscription-Dr-YHARg.mjs} +6 -6
- package/dist/{subscriptions-DCuuPF6U.mjs → subscriptions-8tM8TTeQ.mjs} +6 -6
- package/dist/{summary-uGlgKE3C.mjs → summary-DKx6ptQe.mjs} +5 -5
- package/dist/sync-schema-B8RY0Ra4.mjs +32 -0
- package/dist/{sync-schema-Cu9rD3eH.mjs → sync-schema-kNriXZjG.mjs} +6 -6
- package/dist/sync-task-CXFoqlpF.mjs +53 -0
- package/dist/table-CZnT6d9x.mjs +26 -0
- package/dist/{table-DfuY0N8e.mjs → table-Ci6bhZkb.mjs} +35 -12
- package/dist/table-CxvaDiIZ.mjs +155 -0
- package/dist/table-selector-flags-1bYkAKld.mjs +42 -0
- package/dist/text-DaNkPRwt.mjs +6 -0
- package/dist/timeline-CUzx6uXi.mjs +21 -0
- package/dist/{timeline-event-D-h0A_oh.mjs → timeline-event-DpNm4dkn.mjs} +6 -6
- package/dist/{transform-CtqB1WYo.mjs → transform-CNBIV7No.mjs} +1 -1
- package/dist/transform-g4-HHzDp.mjs +28 -0
- package/dist/transform-job-DqBtnTrG.mjs +22 -0
- package/dist/{transform-tag-BLp_p9J-.mjs → transform-tag-nTb0Ivpj.mjs} +5 -5
- package/dist/{transforms-n2IwEcbU.mjs → transforms-BSsAfwAg.mjs} +5 -5
- package/dist/tree-lMvw1jnZ.mjs +34 -0
- package/dist/{unpublish-DVQCAa3g.mjs → unpublish-CYFDd828.mjs} +3 -3
- package/dist/unreferenced-8Xdq76Kw.mjs +36 -0
- package/dist/{update-oQeQyqKO.mjs → update-6P_GYCLT.mjs} +5 -5
- package/dist/{update-DFdBeJwc.mjs → update-B28EJzrx.mjs} +13 -8
- package/dist/{update-DffrdV4b.mjs → update-BDunZa7G.mjs} +4 -4
- package/dist/{update-DKO9HF1f.mjs → update-BT2yNB_g.mjs} +6 -6
- package/dist/{update-rFRPLlb6.mjs → update-BnMUSFYZ.mjs} +4 -4
- package/dist/update-BwrYeKso.mjs +41 -0
- package/dist/{update-B7CikkI0.mjs → update-C7DEMiu-.mjs} +7 -7
- package/dist/{update-CAsqNhDC.mjs → update-CITzAFG8.mjs} +4 -4
- package/dist/update-CLl8tE20.mjs +181 -0
- package/dist/{update-C05J2nZ2.mjs → update-CM5uuhjB.mjs} +4 -4
- package/dist/{update-ChpOukqq.mjs → update-CQXcsvaa.mjs} +5 -5
- package/dist/{update-D4ggtuG4.mjs → update-Cs2zv_L2.mjs} +7 -7
- package/dist/{update-NGq0yXZk.mjs → update-D--Fw7-_.mjs} +5 -5
- package/dist/{update-D9H6Lh5U.mjs → update-D9p0N8ky.mjs} +4 -4
- package/dist/{update-CKDRuduL.mjs → update-DAzRx0of.mjs} +5 -5
- package/dist/{update-CnkPYL2i.mjs → update-D_DCOOAB.mjs} +6 -6
- package/dist/{update-DScUzKLI.mjs → update-_sYM1GuU.mjs} +7 -7
- package/dist/{update-dashcard-DvPqLJ3N.mjs → update-dashcard-VNnIqHDI.mjs} +6 -6
- package/dist/{upgrade-BRgw0fvn.mjs → upgrade-Tj_reACv.mjs} +4 -4
- package/dist/upload-BKxOpSz3.mjs +13 -0
- package/dist/{upload-Do2PBSeH.mjs → upload-C2fhpKkP.mjs} +2 -2
- package/dist/{upload-BrfbcbBW.mjs → upload-Dg91ldGg.mjs} +3 -3
- package/dist/{uuid-B4eij1d7.mjs → uuid-Blpv_e0S.mjs} +2 -2
- package/dist/{validate-xR_MHBNR.mjs → validate-D7e110oU.mjs} +1 -1
- package/dist/{validate-query-D6_ad-Gi.mjs → validate-query-C7LuKiUT.mjs} +2 -2
- package/dist/{values-xgOftPq5.mjs → values-PonkbYAK.mjs} +5 -5
- package/dist/verify-DixUBbd2.mjs +38 -0
- package/dist/verify-Dv7ER11c.mjs +38 -0
- package/dist/{verify-DTOA_wVM.mjs → verify-Mpb65a5v.mjs} +3 -3
- package/dist/verify-flags-CMpRkMPa.mjs +58 -0
- package/dist/{wait-BjeFgR13.mjs → wait-CaH6XHQV.mjs} +6 -6
- package/dist/{wait-flags-BCeCnaz3.mjs → wait-flags-rUU4NUrv.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/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/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,26 @@
|
|
|
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-CZ5zh32z.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 { a as CardQueryResult,
|
|
8
|
-
import {
|
|
9
|
-
import { t as Database } from "./database-
|
|
7
|
+
import { a as CardQueryResult, d as PivotExportFormat, l as DatasetQuery, t as Card } from "./card-Bv4ZN0oV.mjs";
|
|
8
|
+
import { b as TableVisibilityType, p as TableQueryMetadata, s as TableDataLayerTier, t as Table, u as TableForeignKey, v as TableSelectors } from "./table-Ci6bhZkb.mjs";
|
|
9
|
+
import { t as Database } from "./database-D-CRyRIv.mjs";
|
|
10
10
|
import { t as Snippet } from "./snippet-CyKAgIZl.mjs";
|
|
11
|
-
import {
|
|
11
|
+
import { o as compiledQuerySchema, r as QueryMetadata } from "./dataset-p5oNPQgL.mjs";
|
|
12
|
+
import { c as CollectionItem, m as CollectionTreeNode, r as Collection } from "./collection-D3KXhvnc.mjs";
|
|
12
13
|
import { t as ContentTranslationUploadResult } from "./content-translation-BrHOrmj9.mjs";
|
|
13
|
-
import {
|
|
14
|
-
import { r as pollUntil } from "./poll-
|
|
15
|
-
import { t as
|
|
14
|
+
import { l as Dashcard, o as DashboardDetail, r as DashboardCopy, t as Dashboard } from "./dashboard-Phz3XpRM.mjs";
|
|
15
|
+
import { r as pollUntil } from "./poll-Dz4tUm2f.mjs";
|
|
16
|
+
import { i as DependencyEntity, s as DependencyGraph, t as BreakingSource, u as DependencyNode } from "./dependency-DKSjKT8P.mjs";
|
|
17
|
+
import { t as Document } from "./document-DFCj1Az_.mjs";
|
|
16
18
|
import { i as EidTranslateResult } from "./eid-translation-zEHtr5Oc.mjs";
|
|
17
|
-
import { c as
|
|
18
|
-
import {
|
|
19
|
+
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";
|
|
20
|
+
import { t as Glossary } from "./glossary-BlNCrYbw.mjs";
|
|
21
|
+
import { a as libraryWireSchema, i as LibraryPublishTablesInput, n as LibraryCollectionInfo, o as toLibrary } from "./library-Ck0EK5bi.mjs";
|
|
19
22
|
import { t as Measure } from "./measure-CtfjqJFP.mjs";
|
|
23
|
+
import { r as ModerationReviewCreateInput, t as ModerationReview } from "./moderation-review-BdqEH6N1.mjs";
|
|
20
24
|
import { t as Pulse } from "./pulse-Dz0ocv0l.mjs";
|
|
21
25
|
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
26
|
import { r as SearchResult } from "./search-BAXg-EJw.mjs";
|
|
@@ -349,43 +353,16 @@ async function readBodyForError(response) {
|
|
|
349
353
|
}
|
|
350
354
|
}
|
|
351
355
|
//#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();
|
|
356
|
+
//#region ../client/src/resources/pivot-export.ts
|
|
357
|
+
const PivotedExportsSetting = z.object({ "enable-pivoted-exports": z.boolean() });
|
|
358
|
+
/**
|
|
359
|
+
* Refuse a pivoted export the server would answer with plain rows: a JSON export keeps only the
|
|
360
|
+
* ungrouped rows, and an admin can turn pivoted CSV and XLSX exports off.
|
|
361
|
+
*/
|
|
362
|
+
async function assertPivotedExport(transport, format, options) {
|
|
363
|
+
if (!PivotExportFormat.safeParse(format).success) throw new ConfigError(`a ${format} export cannot be pivoted; only ${PivotExportFormat.options.join(" and ")} can`);
|
|
364
|
+
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");
|
|
365
|
+
}
|
|
389
366
|
//#endregion
|
|
390
367
|
//#region ../client/src/resources/card.ts
|
|
391
368
|
const CardApiList = z.array(Card);
|
|
@@ -442,15 +419,22 @@ function cardResource(transport) {
|
|
|
442
419
|
});
|
|
443
420
|
}
|
|
444
421
|
/**
|
|
445
|
-
* Run a
|
|
446
|
-
* form-encoded body and answers bytes, so a caller
|
|
422
|
+
* Run the query associated with a Card, and return its results as a file in the specified
|
|
423
|
+
* format. Unlike `query`, this endpoint takes a form-encoded body and answers bytes, so a caller
|
|
424
|
+
* consumes the stream rather than a value. A pivot the server would answer with plain rows (a
|
|
425
|
+
* JSON export, or pivoted exports turned off) is refused. `csv_include_bom` opens a CSV with a
|
|
426
|
+
* UTF-8 byte order mark; a server without it drops the key silently, so asking for one is refused
|
|
427
|
+
* there before the wire.
|
|
447
428
|
*/
|
|
448
429
|
async function exportQuery(id, format, params, options = {}) {
|
|
449
430
|
await transport.require("card.exportQuery", options);
|
|
431
|
+
await transport.requireFeatures(params.csv_include_bom ? ["exportCsvByteOrderMark"] : [], options);
|
|
432
|
+
if (params.pivot_results) await assertPivotedExport(transport, format, options);
|
|
450
433
|
const body = new URLSearchParams({
|
|
451
434
|
parameters: JSON.stringify(params.parameters),
|
|
452
435
|
format_rows: String(params.format_rows),
|
|
453
|
-
pivot_results: String(params.pivot_results)
|
|
436
|
+
pivot_results: String(params.pivot_results),
|
|
437
|
+
csv_include_bom: String(params.csv_include_bom)
|
|
454
438
|
});
|
|
455
439
|
return transport.requestStream(`/api/card/${id}/query/${format}`, {
|
|
456
440
|
...options,
|
|
@@ -534,20 +518,20 @@ function refPath(ref) {
|
|
|
534
518
|
return encodeURIComponent(ref);
|
|
535
519
|
}
|
|
536
520
|
/**
|
|
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.
|
|
521
|
+
* List every collection the caller can read, the Library and its children among them, parsing each
|
|
522
|
+
* through the caller's own projection. `Collection` pins `type`, `namespace` and `authority_level`
|
|
523
|
+
* to closed enums, so a consumer reading a few fields off every collection on the instance narrows
|
|
524
|
+
* here: one collection carrying a server value outside those sets then costs nothing to a caller
|
|
525
|
+
* that never reads the field.
|
|
542
526
|
*/
|
|
543
|
-
async function
|
|
544
|
-
return transport.requestParsed(z.array(schema), "/api/collection", {
|
|
545
|
-
...options,
|
|
546
|
-
query: { "include-library": true }
|
|
547
|
-
});
|
|
527
|
+
async function listCollectionsAs(transport, schema, options = {}) {
|
|
528
|
+
return transport.requestParsed(z.array(schema), "/api/collection", { ...options });
|
|
548
529
|
}
|
|
549
530
|
function collectionResource(transport) {
|
|
550
|
-
/**
|
|
531
|
+
/**
|
|
532
|
+
* List collections. `filter` picks a server-side preset: everything, archived, or personal. Every
|
|
533
|
+
* preset includes the Library collections that match it.
|
|
534
|
+
*/
|
|
551
535
|
async function list(params = {}, options = {}) {
|
|
552
536
|
await transport.require("collection.list", options);
|
|
553
537
|
return {
|
|
@@ -558,18 +542,6 @@ function collectionResource(transport) {
|
|
|
558
542
|
total: null
|
|
559
543
|
};
|
|
560
544
|
}
|
|
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
545
|
/** Get one collection by id, entity id, or the `root`/`trash` alias. */
|
|
574
546
|
async function get(ref, options = {}) {
|
|
575
547
|
await transport.require("collection.get", options);
|
|
@@ -584,7 +556,11 @@ function collectionResource(transport) {
|
|
|
584
556
|
body: params
|
|
585
557
|
});
|
|
586
558
|
}
|
|
587
|
-
/**
|
|
559
|
+
/**
|
|
560
|
+
* Update a collection, patching the fields the body carries. The server reads an absent
|
|
561
|
+
* `archived` as `false`, so a patch without it restores an archived collection, and a patch that
|
|
562
|
+
* moves a collection into the trash ignores `parent_id`.
|
|
563
|
+
*/
|
|
588
564
|
async function update(ref, params, options = {}) {
|
|
589
565
|
await transport.require("collection.update", options);
|
|
590
566
|
return transport.requestParsed(Collection, `/api/collection/${refPath(ref)}`, {
|
|
@@ -617,16 +593,18 @@ function collectionResource(transport) {
|
|
|
617
593
|
});
|
|
618
594
|
}
|
|
619
595
|
/** Fetch the collection hierarchy as a forest of nested nodes. */
|
|
620
|
-
async function tree(options = {}) {
|
|
596
|
+
async function tree(params = {}, options = {}) {
|
|
621
597
|
await transport.require("collection.tree", options);
|
|
622
598
|
return {
|
|
623
|
-
data: await transport.requestParsed(CollectionTreeApiList, "/api/collection/tree", {
|
|
599
|
+
data: await transport.requestParsed(CollectionTreeApiList, "/api/collection/tree", {
|
|
600
|
+
...options,
|
|
601
|
+
query: { "include-library": params["include-library"] }
|
|
602
|
+
}),
|
|
624
603
|
total: null
|
|
625
604
|
};
|
|
626
605
|
}
|
|
627
606
|
return {
|
|
628
607
|
list,
|
|
629
|
-
listWithLibrary,
|
|
630
608
|
get,
|
|
631
609
|
create,
|
|
632
610
|
update,
|
|
@@ -715,9 +693,13 @@ function dashboardResource(transport) {
|
|
|
715
693
|
}
|
|
716
694
|
/**
|
|
717
695
|
* Copy a dashboard, with its tabs and dashcards, into `collection_id` (root when absent). A deep
|
|
718
|
-
* copy duplicates
|
|
719
|
-
*
|
|
720
|
-
*
|
|
696
|
+
* copy duplicates its questions and metrics and references its models. With `is_deep_copy`
|
|
697
|
+
* false or absent the copy references every card, and a dashboard holding unarchived dashboard
|
|
698
|
+
* questions is refused. Archived cards, cards the caller cannot read, and every card on a
|
|
699
|
+
* dashcard whose main card the caller cannot read are left out and reported as `uncopied`, once
|
|
700
|
+
* per dashcard they sat on. A left-out main card takes its dashcard with it; a left-out series
|
|
701
|
+
* card stays on a dashcard whose main card is referenced and is dropped from one whose main card
|
|
702
|
+
* is duplicated. Action, link and placeholder dashcards are not copied.
|
|
721
703
|
*/
|
|
722
704
|
async function copy(id, params = {}, options = {}) {
|
|
723
705
|
await transport.require("dashboard.copy", options);
|
|
@@ -971,7 +953,8 @@ function datasetResource(transport) {
|
|
|
971
953
|
*/
|
|
972
954
|
async function native(datasetQuery, params = {}, options = {}) {
|
|
973
955
|
await transport.require("dataset.native", options);
|
|
974
|
-
|
|
956
|
+
const { features } = await transport.server(options);
|
|
957
|
+
return transport.requestParsed(compiledQuerySchema(features), "/api/dataset/native", {
|
|
975
958
|
...options,
|
|
976
959
|
method: "POST",
|
|
977
960
|
body: {
|
|
@@ -994,18 +977,33 @@ function datasetResource(transport) {
|
|
|
994
977
|
});
|
|
995
978
|
}
|
|
996
979
|
/**
|
|
997
|
-
*
|
|
998
|
-
* bytes, so a caller consumes the stream rather than a value.
|
|
980
|
+
* Execute a query and download the result data as a file in the specified format. Unlike
|
|
981
|
+
* `query`, this endpoint answers bytes, so a caller consumes the stream rather than a value.
|
|
982
|
+
* `visualization_settings` drive `format_rows` column formatting and, through
|
|
983
|
+
* `pivot_table.column_split`, the layout `pivot_results` lays the rows out in. The server only
|
|
984
|
+
* computes that layout for a query it runs as a pivot, which it reads from the query's own
|
|
985
|
+
* `was-pivot`, so `pivot_results` sets it. A pivot the server would answer with plain rows (a
|
|
986
|
+
* JSON export, or pivoted exports turned off) is refused. `csv_include_bom` opens a CSV with a
|
|
987
|
+
* UTF-8 byte order mark; a server without it drops the key silently, so asking for one is refused
|
|
988
|
+
* there before the wire.
|
|
999
989
|
*/
|
|
1000
990
|
async function exportQuery(format, params, options = {}) {
|
|
1001
991
|
await transport.require("dataset.exportQuery", options);
|
|
992
|
+
await transport.requireFeatures(params.csv_include_bom ? ["exportCsvByteOrderMark"] : [], options);
|
|
993
|
+
if (params.pivot_results) await assertPivotedExport(transport, format, options);
|
|
994
|
+
const exported = params.pivot_results ? {
|
|
995
|
+
...params.query,
|
|
996
|
+
"was-pivot": true
|
|
997
|
+
} : params.query;
|
|
1002
998
|
return transport.requestStream(`/api/dataset/${format}`, {
|
|
1003
999
|
...options,
|
|
1004
1000
|
method: "POST",
|
|
1005
1001
|
body: {
|
|
1006
|
-
query:
|
|
1002
|
+
query: exported,
|
|
1003
|
+
visualization_settings: params.visualization_settings,
|
|
1007
1004
|
format_rows: params.format_rows,
|
|
1008
|
-
pivot_results: params.pivot_results
|
|
1005
|
+
pivot_results: params.pivot_results,
|
|
1006
|
+
csv_include_bom: params.csv_include_bom
|
|
1009
1007
|
}
|
|
1010
1008
|
});
|
|
1011
1009
|
}
|
|
@@ -1017,133 +1015,18 @@ function datasetResource(transport) {
|
|
|
1017
1015
|
};
|
|
1018
1016
|
}
|
|
1019
1017
|
//#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
1018
|
//#region ../client/src/resources/dependency.ts
|
|
1126
1019
|
const DependencyNodeApiList = z.array(DependencyNode);
|
|
1127
1020
|
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
1021
|
function dependencyResource(transport) {
|
|
1140
1022
|
/**
|
|
1141
1023
|
* The upstream dependency graph of one entity. `nodes` holds the starting entity plus every
|
|
1142
1024
|
* entity it depends on, directly or transitively; each edge runs from the dependent to what it
|
|
1143
|
-
* depends on.
|
|
1025
|
+
* depends on. A measure starts a graph only on a server with `measureDependencyGraph`.
|
|
1144
1026
|
*/
|
|
1145
1027
|
async function graph(type, id, options = {}) {
|
|
1146
1028
|
await transport.require("dependency.graph", options);
|
|
1029
|
+
if (type === "measure") await transport.requireFeatures(["measureDependencyGraph"], options);
|
|
1147
1030
|
return transport.requestParsed(DependencyGraph, "/api/ee/dependencies/graph", {
|
|
1148
1031
|
...options,
|
|
1149
1032
|
query: {
|
|
@@ -1160,7 +1043,6 @@ function dependencyResource(transport) {
|
|
|
1160
1043
|
*/
|
|
1161
1044
|
async function dependents(type, id, params = {}, options = {}) {
|
|
1162
1045
|
await transport.require("dependency.dependents", options);
|
|
1163
|
-
await transport.requireFeatures(filterFeatures(params), options);
|
|
1164
1046
|
return {
|
|
1165
1047
|
data: await transport.requestParsed(DependencyNodeApiList, "/api/ee/dependencies/graph/dependents", {
|
|
1166
1048
|
...options,
|
|
@@ -1187,7 +1069,6 @@ function dependencyResource(transport) {
|
|
|
1187
1069
|
*/
|
|
1188
1070
|
async function broken(type, id, params = {}, options = {}) {
|
|
1189
1071
|
await transport.require("dependency.broken", options);
|
|
1190
|
-
await transport.requireFeatures(filterFeatures(params), options);
|
|
1191
1072
|
return {
|
|
1192
1073
|
data: await transport.requestParsed(DependencyEntityApiList, "/api/ee/dependencies/graph/broken", {
|
|
1193
1074
|
...options,
|
|
@@ -1205,15 +1086,23 @@ function dependencyResource(transport) {
|
|
|
1205
1086
|
};
|
|
1206
1087
|
}
|
|
1207
1088
|
/**
|
|
1208
|
-
* Walk the entities
|
|
1209
|
-
*
|
|
1089
|
+
* Walk the entities that no readable, unarchived dependent depends on, one page at a time: an
|
|
1090
|
+
* entity used only by archived content, or by content the caller cannot read, is listed. `types`
|
|
1091
|
+
* and `card-types` narrow which kinds are listed, `query` matches against names and locations,
|
|
1210
1092
|
* `include-personal-collections` admits content in personal collections, and `sort-column` /
|
|
1211
|
-
* `sort-direction` order the result.
|
|
1212
|
-
*
|
|
1093
|
+
* `sort-direction` order the result. A `query` leaves sandboxes out, since they have no name or
|
|
1094
|
+
* location to match, so sandboxes alone with a `query` answer one empty page without a request.
|
|
1095
|
+
* This endpoint pages on the server, so the caller consumes pages and decides how far to pull.
|
|
1213
1096
|
*/
|
|
1214
1097
|
async function* unreferencedPages(params = {}, options = {}) {
|
|
1215
1098
|
await transport.require("dependency.unreferencedPages", options);
|
|
1216
|
-
|
|
1099
|
+
if (queryLeavesNoKind(params)) {
|
|
1100
|
+
yield {
|
|
1101
|
+
items: [],
|
|
1102
|
+
total: 0
|
|
1103
|
+
};
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1217
1106
|
yield* paginatePages(transport, "/api/ee/dependencies/graph/unreferenced", DependencyNode, {
|
|
1218
1107
|
query: itemListQuery(params),
|
|
1219
1108
|
...options.offset !== void 0 && { offset: options.offset },
|
|
@@ -1231,7 +1120,13 @@ function dependencyResource(transport) {
|
|
|
1231
1120
|
*/
|
|
1232
1121
|
async function* breakingPages(params = {}, options = {}) {
|
|
1233
1122
|
await transport.require("dependency.breakingPages", options);
|
|
1234
|
-
|
|
1123
|
+
if (queryLeavesNoKind(params)) {
|
|
1124
|
+
yield {
|
|
1125
|
+
items: [],
|
|
1126
|
+
total: 0
|
|
1127
|
+
};
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1235
1130
|
yield* paginatePages(transport, "/api/ee/dependencies/graph/breaking", BreakingSource, {
|
|
1236
1131
|
query: itemListQuery(params),
|
|
1237
1132
|
...options.offset !== void 0 && { offset: options.offset },
|
|
@@ -1248,9 +1143,14 @@ function dependencyResource(transport) {
|
|
|
1248
1143
|
breakingPages
|
|
1249
1144
|
};
|
|
1250
1145
|
}
|
|
1146
|
+
function queryLeavesNoKind(params) {
|
|
1147
|
+
const { query, types } = params;
|
|
1148
|
+
if (query === void 0 || types === void 0 || types.length === 0) return false;
|
|
1149
|
+
return types.every((type) => type === "sandbox");
|
|
1150
|
+
}
|
|
1251
1151
|
function itemListQuery(params) {
|
|
1252
1152
|
return {
|
|
1253
|
-
types: params.types,
|
|
1153
|
+
types: params.types === void 0 ? void 0 : [...new Set(params.types)],
|
|
1254
1154
|
"card-types": params["card-types"],
|
|
1255
1155
|
query: params.query,
|
|
1256
1156
|
"include-personal-collections": params["include-personal-collections"],
|
|
@@ -1417,21 +1317,39 @@ async function fetchOptionalParsed(client, path, schema, options = {}) {
|
|
|
1417
1317
|
//#region ../client/src/resources/field.ts
|
|
1418
1318
|
const FieldApiSummary = z.tuple([z.tuple([z.literal("count"), z.number().int()]), z.tuple([z.literal("distincts"), z.number().int()])]);
|
|
1419
1319
|
function fieldResource(transport) {
|
|
1420
|
-
/**
|
|
1320
|
+
/**
|
|
1321
|
+
* Get one field by id. A server that labels data sensitivity answers `data_sensitivity`, `null`
|
|
1322
|
+
* for an unlabelled field; any other answers the field without the key (`hasDataSensitivity`).
|
|
1323
|
+
*/
|
|
1421
1324
|
async function get(id, options = {}) {
|
|
1422
1325
|
await transport.require("field.get", options);
|
|
1423
|
-
|
|
1326
|
+
const { features } = await transport.server(options);
|
|
1327
|
+
return transport.requestParsed(fieldDetailSchema(features), `/api/field/${id}`, { ...options });
|
|
1424
1328
|
}
|
|
1425
1329
|
/**
|
|
1426
1330
|
* Update a field by id, patching only the fields the body carries. A `data_sensitivity` label is
|
|
1427
1331
|
* a person's call the server's classifier never overwrites, and `null` withdraws it so the
|
|
1428
1332
|
* 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.
|
|
1333
|
+
* the label is refused there before the wire. Answers the field the way `get` does.
|
|
1430
1334
|
*/
|
|
1431
1335
|
async function update(id, params, options = {}) {
|
|
1432
1336
|
await transport.require("field.update", options);
|
|
1433
1337
|
await transport.requireFeatures(params.data_sensitivity === void 0 ? [] : ["fieldDataSensitivity"], options);
|
|
1434
|
-
|
|
1338
|
+
const { features } = await transport.server(options);
|
|
1339
|
+
return transport.requestParsed(fieldDetailSchema(features), `/api/field/${id}`, {
|
|
1340
|
+
...options,
|
|
1341
|
+
method: "PUT",
|
|
1342
|
+
body: params
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* Label a field's data sensitivity by hand. A person's label is never overwritten by the server's
|
|
1347
|
+
* classifier; `null` withdraws it, so whatever label the classifier wrote shows again. Answers
|
|
1348
|
+
* the field with the label it now carries.
|
|
1349
|
+
*/
|
|
1350
|
+
async function setDataSensitivity(id, params, options = {}) {
|
|
1351
|
+
await transport.require("field.setDataSensitivity", options);
|
|
1352
|
+
return transport.requestParsed(FieldWithDataSensitivity, `/api/field/${id}`, {
|
|
1435
1353
|
...options,
|
|
1436
1354
|
method: "PUT",
|
|
1437
1355
|
body: params
|
|
@@ -1439,8 +1357,11 @@ function fieldResource(transport) {
|
|
|
1439
1357
|
}
|
|
1440
1358
|
/**
|
|
1441
1359
|
* Search the values of `searchId` that contain `value`, case-insensitively, answering the
|
|
1442
|
-
* matching values of `id` paired with them
|
|
1443
|
-
* points at
|
|
1360
|
+
* matching values of `id` paired with them, ordered by value, at most `limit` of them. An FK on
|
|
1361
|
+
* either side is followed to the PK it points at, and a field that resolves to the same field as
|
|
1362
|
+
* `searchId` answers each value alone. Without `value`, the first `limit` values. A field with
|
|
1363
|
+
* custom display values answers every mapped value with its display value instead, matching
|
|
1364
|
+
* `value` against the display value, ignoring both `searchId` and `limit`.
|
|
1444
1365
|
*/
|
|
1445
1366
|
async function search(id, searchId, params, options = {}) {
|
|
1446
1367
|
await transport.require("field.search", options);
|
|
@@ -1454,11 +1375,13 @@ function fieldResource(transport) {
|
|
|
1454
1375
|
}
|
|
1455
1376
|
/**
|
|
1456
1377
|
* The value of `remappedId` on the one row where `id` equals `value`, as `[value, remapped]`,
|
|
1457
|
-
* or `null` when no row matches.
|
|
1378
|
+
* or `null` when no row matches. For a numeric field the server reads the leading number of
|
|
1379
|
+
* `value` and ignores any text after it, refusing only a `value` that has none.
|
|
1458
1380
|
*/
|
|
1459
1381
|
async function remapping(id, remappedId, params, options = {}) {
|
|
1460
1382
|
await transport.require("field.remapping", options);
|
|
1461
|
-
|
|
1383
|
+
const { features } = await transport.server(options);
|
|
1384
|
+
return fetchOptionalParsed(transport, `/api/field/${id}/remapping/${remappedId}`, fieldRemappedValueSchema(features, id === remappedId), {
|
|
1462
1385
|
...options,
|
|
1463
1386
|
query: { value: params.value }
|
|
1464
1387
|
});
|
|
@@ -1481,6 +1404,7 @@ function fieldResource(transport) {
|
|
|
1481
1404
|
return {
|
|
1482
1405
|
get,
|
|
1483
1406
|
update,
|
|
1407
|
+
setDataSensitivity,
|
|
1484
1408
|
search,
|
|
1485
1409
|
remapping,
|
|
1486
1410
|
summary,
|
|
@@ -1512,6 +1436,7 @@ const SyncStashStarted = z.object({
|
|
|
1512
1436
|
task_id: z.number().int().positive()
|
|
1513
1437
|
});
|
|
1514
1438
|
const RemoteSyncSetting = z.string().nullable();
|
|
1439
|
+
const RemoteSyncBranchProperty = z.object({ "remote-sync-branch": z.string().nullable().optional() });
|
|
1515
1440
|
const FORBIDDEN_STATUS = 403;
|
|
1516
1441
|
const UNREGISTERED_STATUS = 404;
|
|
1517
1442
|
function isRemoteUnreadable(error) {
|
|
@@ -1559,16 +1484,24 @@ function gitSyncResource(transport) {
|
|
|
1559
1484
|
/**
|
|
1560
1485
|
* Import content from the remote into Metabase. The endpoint queues a task and returns at once;
|
|
1561
1486
|
* 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.
|
|
1487
|
+
* answers no task id, and there is then nothing to poll. A server that guards the tracked branch
|
|
1488
|
+
* refuses with 409 when `expected_branch` disagrees with the setting; left out, it is the tracked
|
|
1489
|
+
* branch as read just before the request. `merge` folds the remote's changes into local content
|
|
1490
|
+
* by a three-way merge and keeps un-pushed local changes, where a plain import refuses on a dirty
|
|
1491
|
+
* instance.
|
|
1563
1492
|
*/
|
|
1564
1493
|
async function importFromRemote(params = {}, options = {}) {
|
|
1565
1494
|
await transport.require("gitSync.import", options);
|
|
1495
|
+
await requireMerge(params.merge, options);
|
|
1496
|
+
const expectedBranch = await guardedBranch(params.expected_branch, options);
|
|
1566
1497
|
const started = await transport.requestParsed(SyncImportStarted, "/api/ee/remote-sync/import", {
|
|
1567
1498
|
...options,
|
|
1568
1499
|
method: "POST",
|
|
1569
1500
|
body: {
|
|
1570
1501
|
branch: params.branch,
|
|
1571
|
-
force: params.force
|
|
1502
|
+
force: params.force,
|
|
1503
|
+
merge: params.merge,
|
|
1504
|
+
expected_branch: expectedBranch
|
|
1572
1505
|
}
|
|
1573
1506
|
});
|
|
1574
1507
|
const message = started.message ?? null;
|
|
@@ -1582,19 +1515,36 @@ function gitSyncResource(transport) {
|
|
|
1582
1515
|
final: await settle(params.wait, options)
|
|
1583
1516
|
};
|
|
1584
1517
|
}
|
|
1518
|
+
async function requireMerge(merge, options) {
|
|
1519
|
+
if (merge === true) await transport.requireFeatures(["remoteSyncMerge"], options);
|
|
1520
|
+
}
|
|
1521
|
+
async function guardedBranch(given, options) {
|
|
1522
|
+
if (given !== void 0) return given;
|
|
1523
|
+
const { features } = await transport.server(options);
|
|
1524
|
+
if (!features.remoteSyncBranchGuard) return;
|
|
1525
|
+
return trackedBranch(options);
|
|
1526
|
+
}
|
|
1585
1527
|
/**
|
|
1586
1528
|
* 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.
|
|
1529
|
+
* `wait` to poll that task until it reaches a terminal status. A server that guards the tracked
|
|
1530
|
+
* branch refuses with 409 when `branch` is not the tracked one; left out, it is the tracked branch
|
|
1531
|
+
* as read just before the request there, and the server's own default elsewhere. When the remote
|
|
1532
|
+
* has moved past the last sync, a plain export ends in a `conflict` task where `merge` is
|
|
1533
|
+
* available, and is refused with 400 before any task elsewhere; `merge` folds the remote's changes
|
|
1534
|
+
* in by a three-way merge instead, and `force` overwrites them.
|
|
1588
1535
|
*/
|
|
1589
1536
|
async function exportToRemote(params = {}, options = {}) {
|
|
1590
1537
|
await transport.require("gitSync.export", options);
|
|
1538
|
+
await requireMerge(params.merge, options);
|
|
1539
|
+
const branchName = await guardedBranch(params.branch, options);
|
|
1591
1540
|
const started = await transport.requestParsed(SyncExportStarted, "/api/ee/remote-sync/export", {
|
|
1592
1541
|
...options,
|
|
1593
1542
|
method: "POST",
|
|
1594
1543
|
body: {
|
|
1595
|
-
branch:
|
|
1544
|
+
branch: branchName,
|
|
1596
1545
|
message: params.message,
|
|
1597
|
-
force: params.force
|
|
1546
|
+
force: params.force,
|
|
1547
|
+
merge: params.merge
|
|
1598
1548
|
}
|
|
1599
1549
|
});
|
|
1600
1550
|
if (params.wait === void 0) return {
|
|
@@ -1679,7 +1629,7 @@ function gitSyncResource(transport) {
|
|
|
1679
1629
|
async function syncedCollections(options = {}) {
|
|
1680
1630
|
await transport.require("gitSync.syncedCollections", options);
|
|
1681
1631
|
return {
|
|
1682
|
-
data: (await
|
|
1632
|
+
data: (await listCollectionsAs(transport, SyncScopeCollection, options)).filter((entry) => entry.is_remote_synced === true),
|
|
1683
1633
|
total: null
|
|
1684
1634
|
};
|
|
1685
1635
|
}
|
|
@@ -1695,17 +1645,22 @@ function gitSyncResource(transport) {
|
|
|
1695
1645
|
}
|
|
1696
1646
|
}
|
|
1697
1647
|
/**
|
|
1698
|
-
* The branch git-sync tracks, or null when none is configured
|
|
1699
|
-
* the server has no remote-sync module
|
|
1648
|
+
* The branch git-sync tracks, or null when none is configured. Refuses when the caller may not
|
|
1649
|
+
* read the setting (it is admin-only) or the server has no remote-sync module, rather than
|
|
1650
|
+
* reading either as unset.
|
|
1700
1651
|
*/
|
|
1701
1652
|
async function branch(options = {}) {
|
|
1702
1653
|
await transport.require("gitSync.branch", options);
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1654
|
+
const tracked = (await transport.requestParsed(RemoteSyncBranchProperty, PROBE_PATH, { ...options }))["remote-sync-branch"];
|
|
1655
|
+
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");
|
|
1656
|
+
return tracked;
|
|
1657
|
+
}
|
|
1658
|
+
/** The branch git-sync tracks, refused when none is configured or the caller may not read it. */
|
|
1659
|
+
async function trackedBranch(options = {}) {
|
|
1660
|
+
await transport.require("gitSync.trackedBranch", options);
|
|
1661
|
+
const tracked = await branch(options);
|
|
1662
|
+
if (tracked === null) throw new ConfigError("git-sync tracks no branch: the remote-sync-branch setting is unset");
|
|
1663
|
+
return tracked;
|
|
1709
1664
|
}
|
|
1710
1665
|
/**
|
|
1711
1666
|
* Poll the current task until it reaches a terminal status. A server with no task at all
|
|
@@ -1737,36 +1692,11 @@ function gitSyncResource(transport) {
|
|
|
1737
1692
|
syncedCollections,
|
|
1738
1693
|
remoteUrl,
|
|
1739
1694
|
branch,
|
|
1695
|
+
trackedBranch,
|
|
1740
1696
|
waitForTask
|
|
1741
1697
|
};
|
|
1742
1698
|
}
|
|
1743
1699
|
//#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
1700
|
//#region ../client/src/resources/glossary.ts
|
|
1771
1701
|
const GlossaryApiList = z.object({ data: z.array(Glossary) }).loose();
|
|
1772
1702
|
function glossaryResource(transport) {
|
|
@@ -1819,6 +1749,17 @@ function glossaryResource(transport) {
|
|
|
1819
1749
|
};
|
|
1820
1750
|
}
|
|
1821
1751
|
//#endregion
|
|
1752
|
+
//#region ../client/src/resources/request-body.ts
|
|
1753
|
+
/**
|
|
1754
|
+
* Parse the body a caller hands a method, refusing one that does not match `schema` before any
|
|
1755
|
+
* request. `what` names the body in the refusal.
|
|
1756
|
+
*/
|
|
1757
|
+
function parseRequestBody(schema, value, what) {
|
|
1758
|
+
const parsed = schema.safeParse(value);
|
|
1759
|
+
if (!parsed.success) throw new ConfigError(`invalid ${what}: ${parsed.error.issues.map(formatZodIssue).join("; ")}`);
|
|
1760
|
+
return parsed.data;
|
|
1761
|
+
}
|
|
1762
|
+
//#endregion
|
|
1822
1763
|
//#region ../client/src/resources/library.ts
|
|
1823
1764
|
const LIBRARY_ROOT_PATH = "/api/ee/library/";
|
|
1824
1765
|
const PUBLISH_TABLES_PATH = "/api/ee/data-studio/table/publish-tables";
|
|
@@ -1835,7 +1776,7 @@ function libraryResource(transport) {
|
|
|
1835
1776
|
return toLibrary(wire, await libraryListing(options));
|
|
1836
1777
|
}
|
|
1837
1778
|
async function libraryListing(options) {
|
|
1838
|
-
const data = await
|
|
1779
|
+
const data = await listCollectionsAs(transport, LibraryCollectionInfo, options);
|
|
1839
1780
|
const byId = /* @__PURE__ */ new Map();
|
|
1840
1781
|
for (const collection of data) if (typeof collection.id === "number") byId.set(collection.id, collection);
|
|
1841
1782
|
return byId;
|
|
@@ -1868,26 +1809,31 @@ function libraryResource(transport) {
|
|
|
1868
1809
|
}
|
|
1869
1810
|
/**
|
|
1870
1811
|
* 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.
|
|
1812
|
+
* data pickers and rank up in search. Answers the collection they landed in. The endpoint
|
|
1813
|
+
* answers the same whether or not the selectors matched a table, so a body that does not match
|
|
1814
|
+
* `LibraryPublishTablesInput` is refused before any request.
|
|
1872
1815
|
*/
|
|
1873
1816
|
async function publishTables(params, options = {}) {
|
|
1874
1817
|
await transport.require("library.publishTables", options);
|
|
1818
|
+
const body = parseRequestBody(LibraryPublishTablesInput, params, "tables to publish");
|
|
1875
1819
|
return (await transport.requestParsed(PublishTablesResponse, PUBLISH_TABLES_PATH, {
|
|
1876
1820
|
...options,
|
|
1877
1821
|
method: "POST",
|
|
1878
|
-
body
|
|
1822
|
+
body
|
|
1879
1823
|
})).target_collection;
|
|
1880
1824
|
}
|
|
1881
1825
|
/**
|
|
1882
1826
|
* Clear the Library collection from tables, and recursively from every downstream table that
|
|
1883
|
-
* depends on them. The endpoint answers no JSON body
|
|
1827
|
+
* depends on them. The endpoint answers no JSON body, whether or not the selectors matched a
|
|
1828
|
+
* table, so selectors that do not match `TableSelectors` are refused before any request.
|
|
1884
1829
|
*/
|
|
1885
1830
|
async function unpublishTables(params, options = {}) {
|
|
1886
1831
|
await transport.require("library.unpublishTables", options);
|
|
1832
|
+
const body = parseRequestBody(TableSelectors, params, "table selectors");
|
|
1887
1833
|
await transport.requestRaw(UNPUBLISH_TABLES_PATH, {
|
|
1888
1834
|
...options,
|
|
1889
1835
|
method: "POST",
|
|
1890
|
-
body
|
|
1836
|
+
body,
|
|
1891
1837
|
expectContentType: "binary"
|
|
1892
1838
|
});
|
|
1893
1839
|
}
|
|
@@ -2140,48 +2086,21 @@ function metricResource(transport) {
|
|
|
2140
2086
|
};
|
|
2141
2087
|
}
|
|
2142
2088
|
//#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
2089
|
//#region ../client/src/resources/moderation-review.ts
|
|
2173
2090
|
function moderationReviewResource(transport) {
|
|
2174
2091
|
/**
|
|
2175
2092
|
* Create a moderation review on a card or dashboard. `status: "verified"` marks the item
|
|
2176
2093
|
* verified, `null` or an absent status records a note that leaves it unverified. The new review
|
|
2177
2094
|
* becomes the item's most recent one; the server keeps the ten newest per item. Admins only.
|
|
2095
|
+
* A body that does not match `ModerationReviewCreateInput` is refused before any request.
|
|
2178
2096
|
*/
|
|
2179
2097
|
async function create(params, options = {}) {
|
|
2180
2098
|
await transport.require("moderationReview.create", options);
|
|
2099
|
+
const body = parseRequestBody(ModerationReviewCreateInput, params, "moderation review");
|
|
2181
2100
|
return transport.requestParsed(ModerationReview, "/api/moderation-review", {
|
|
2182
2101
|
...options,
|
|
2183
2102
|
method: "POST",
|
|
2184
|
-
body
|
|
2103
|
+
body
|
|
2185
2104
|
});
|
|
2186
2105
|
}
|
|
2187
2106
|
return { create };
|
|
@@ -2702,8 +2621,10 @@ function searchResource(transport) {
|
|
|
2702
2621
|
* may match, `archived` swaps the active set for the archived one, `table_db_id` restricts to
|
|
2703
2622
|
* items on one database, `verified` to verified content, `collection` to one collection and its
|
|
2704
2623
|
* descendants, `created_by` to items created by any of those users, `search_native_query` also
|
|
2705
|
-
* matches
|
|
2706
|
-
*
|
|
2624
|
+
* matches native query text but narrows to the models that carry one (cards, models, metrics,
|
|
2625
|
+
* actions, transforms), `include_metadata` attaches each card's `result_metadata`,
|
|
2626
|
+
* `include_dashboard_questions` also matches questions saved into a dashboard (excluded by
|
|
2627
|
+
* default), and `limit`/`offset` are the window the server applies before ranking hydration.
|
|
2707
2628
|
*/
|
|
2708
2629
|
async function query(params = {}, options = {}) {
|
|
2709
2630
|
await transport.require("search.query", options);
|
|
@@ -2720,7 +2641,8 @@ function searchResource(transport) {
|
|
|
2720
2641
|
collection: params.collection,
|
|
2721
2642
|
created_by: params.created_by,
|
|
2722
2643
|
search_native_query: params.search_native_query,
|
|
2723
|
-
include_metadata: params.include_metadata
|
|
2644
|
+
include_metadata: params.include_metadata,
|
|
2645
|
+
include_dashboard_questions: params.include_dashboard_questions
|
|
2724
2646
|
}
|
|
2725
2647
|
});
|
|
2726
2648
|
return {
|
|
@@ -2904,14 +2826,18 @@ function snippetResource(transport) {
|
|
|
2904
2826
|
const TableApiList = z.array(Table);
|
|
2905
2827
|
const TableApiFks = z.array(TableForeignKey);
|
|
2906
2828
|
const SyncSchemaResponse = z.object({ status: z.literal("ok") });
|
|
2907
|
-
const
|
|
2829
|
+
const FieldValuesResponse = z.object({ status: z.literal("success") });
|
|
2908
2830
|
const BulkEditResponse = z.object({});
|
|
2909
2831
|
const BULK_EDIT_PATH = "/api/data-studio/table/edit";
|
|
2832
|
+
const BULK_SYNC_SCHEMA_PATH = "/api/data-studio/table/sync-schema";
|
|
2833
|
+
const BULK_RESCAN_VALUES_PATH = "/api/data-studio/table/rescan-values";
|
|
2834
|
+
const BULK_DISCARD_VALUES_PATH = "/api/data-studio/table/discard-values";
|
|
2910
2835
|
const LIST_PARAM_FEATURES = [
|
|
2911
2836
|
["can-query", "tableListAccessFilters"],
|
|
2912
2837
|
["can-write", "tableListAccessFilters"],
|
|
2913
2838
|
["include-transform-targets", "tableListTransformTargets"],
|
|
2914
|
-
["unused-only", "tableUnusedFilter"]
|
|
2839
|
+
["unused-only", "tableUnusedFilter"],
|
|
2840
|
+
["published-only", "tableListPublishedFilter"]
|
|
2915
2841
|
];
|
|
2916
2842
|
function listParamFeatures(params) {
|
|
2917
2843
|
return LIST_PARAM_FEATURES.filter(([param]) => params[param] !== void 0).map(([, feature]) => feature);
|
|
@@ -2925,7 +2851,7 @@ function tableResource(transport) {
|
|
|
2925
2851
|
* List every table the caller can see, across all databases. `term` matches names and display
|
|
2926
2852
|
* names; `can-query` and `can-write` keep only the tables the caller may query or edit the
|
|
2927
2853
|
* metadata of; `include-transform-targets` adds tables a transform writes to; `unused-only` keeps
|
|
2928
|
-
* tables nothing depends on.
|
|
2854
|
+
* tables nothing depends on; `published-only` keeps tables published to the library.
|
|
2929
2855
|
*/
|
|
2930
2856
|
async function list(params = {}, options = {}) {
|
|
2931
2857
|
await transport.require("table.list", options);
|
|
@@ -2943,6 +2869,7 @@ function tableResource(transport) {
|
|
|
2943
2869
|
"owner-email": params["owner-email"],
|
|
2944
2870
|
"orphan-only": params["orphan-only"],
|
|
2945
2871
|
"unused-only": params["unused-only"],
|
|
2872
|
+
"published-only": params["published-only"],
|
|
2946
2873
|
"can-query": params["can-query"],
|
|
2947
2874
|
"can-write": params["can-write"],
|
|
2948
2875
|
"include-transform-targets": params["include-transform-targets"]
|
|
@@ -2992,38 +2919,107 @@ function tableResource(transport) {
|
|
|
2992
2919
|
};
|
|
2993
2920
|
}
|
|
2994
2921
|
/**
|
|
2995
|
-
* Trigger a
|
|
2996
|
-
*
|
|
2922
|
+
* Trigger a sync of this table: its columns, their fingerprints and its cached field values. It
|
|
2923
|
+
* never discovers new tables. The sync runs after the call returns; a warehouse the server cannot
|
|
2924
|
+
* connect to is a 422.
|
|
2997
2925
|
*/
|
|
2998
2926
|
async function syncSchema(id, options = {}) {
|
|
2999
2927
|
await transport.require("table.syncSchema", options);
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
2928
|
+
return {
|
|
2929
|
+
id,
|
|
2930
|
+
status: (await transport.requestParsed(SyncSchemaResponse, `/api/table/${id}/sync_schema`, {
|
|
2931
|
+
...options,
|
|
2932
|
+
method: "POST"
|
|
2933
|
+
})).status
|
|
2934
|
+
};
|
|
3004
2935
|
}
|
|
3005
2936
|
/**
|
|
3006
|
-
* Trigger an update of the field values of every eligible field of this table
|
|
3007
|
-
* after the call returns.
|
|
2937
|
+
* Trigger an update of the field values of every eligible field of this table that already has a
|
|
2938
|
+
* cached set. The scan runs after the call returns.
|
|
3008
2939
|
*/
|
|
3009
2940
|
async function rescanValues(id, options = {}) {
|
|
3010
2941
|
await transport.require("table.rescanValues", options);
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
2942
|
+
return {
|
|
2943
|
+
id,
|
|
2944
|
+
status: (await transport.requestParsed(FieldValuesResponse, `/api/table/${id}/rescan_values`, {
|
|
2945
|
+
...options,
|
|
2946
|
+
method: "POST"
|
|
2947
|
+
})).status
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Discard the cached field values of every field of this table, custom display values included.
|
|
2952
|
+
* No scan recreates a discarded set; the server rebuilds it, without the display values, the next
|
|
2953
|
+
* time the field's values are read.
|
|
2954
|
+
*/
|
|
2955
|
+
async function discardValues(id, options = {}) {
|
|
2956
|
+
await transport.require("table.discardValues", options);
|
|
2957
|
+
return {
|
|
2958
|
+
id,
|
|
2959
|
+
status: (await transport.requestParsed(FieldValuesResponse, `/api/table/${id}/discard_values`, {
|
|
2960
|
+
...options,
|
|
2961
|
+
method: "POST"
|
|
2962
|
+
})).status
|
|
2963
|
+
};
|
|
3015
2964
|
}
|
|
3016
2965
|
/**
|
|
3017
2966
|
* 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.
|
|
2967
|
+
* layer is re-synced after the call returns. The server answers the same whether or not the
|
|
2968
|
+
* selectors matched a table.
|
|
3019
2969
|
*/
|
|
3020
2970
|
async function bulkEdit(params, options = {}) {
|
|
3021
2971
|
await transport.require("table.bulkEdit", options);
|
|
2972
|
+
await requireDataAuthorityNull(params.data_authority, options);
|
|
3022
2973
|
await transport.requestParsed(BulkEditResponse, BULK_EDIT_PATH, {
|
|
3023
2974
|
...options,
|
|
3024
2975
|
method: "POST",
|
|
3025
2976
|
body: params
|
|
3026
2977
|
});
|
|
2978
|
+
return {
|
|
2979
|
+
accepted: true,
|
|
2980
|
+
...params
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
async function requireDataAuthorityNull(value, options) {
|
|
2984
|
+
if (value === null) await transport.requireFeatures(["tableUserValueWithdrawal"], options);
|
|
2985
|
+
}
|
|
2986
|
+
async function postSelection(path, selectors, options) {
|
|
2987
|
+
const body = parseRequestBody(TableSelectors, selectors, "table selectors");
|
|
2988
|
+
await transport.requestRaw(path, {
|
|
2989
|
+
...options,
|
|
2990
|
+
method: "POST",
|
|
2991
|
+
body,
|
|
2992
|
+
expectContentType: "binary"
|
|
2993
|
+
});
|
|
2994
|
+
return {
|
|
2995
|
+
accepted: true,
|
|
2996
|
+
...body
|
|
2997
|
+
};
|
|
2998
|
+
}
|
|
2999
|
+
/**
|
|
3000
|
+
* Trigger a sync of every table the selectors pick out: its columns, their fingerprints and its
|
|
3001
|
+
* cached field values. Every database behind them must answer a connection test first, or the
|
|
3002
|
+
* call is a 422; the syncs run after it returns.
|
|
3003
|
+
*/
|
|
3004
|
+
async function bulkSyncSchema(selectors, options = {}) {
|
|
3005
|
+
await transport.require("table.bulkSyncSchema", options);
|
|
3006
|
+
return postSelection(BULK_SYNC_SCHEMA_PATH, selectors, options);
|
|
3007
|
+
}
|
|
3008
|
+
/**
|
|
3009
|
+
* Trigger a field-values rescan of every table the selectors pick out, refreshing the sets that
|
|
3010
|
+
* are already cached. The scans run after the call returns.
|
|
3011
|
+
*/
|
|
3012
|
+
async function bulkRescanValues(selectors, options = {}) {
|
|
3013
|
+
await transport.require("table.bulkRescanValues", options);
|
|
3014
|
+
return postSelection(BULK_RESCAN_VALUES_PATH, selectors, options);
|
|
3015
|
+
}
|
|
3016
|
+
/**
|
|
3017
|
+
* Discard the cached field values of every table the selectors pick out, custom display values
|
|
3018
|
+
* included. No scan recreates a discarded set.
|
|
3019
|
+
*/
|
|
3020
|
+
async function bulkDiscardValues(selectors, options = {}) {
|
|
3021
|
+
await transport.require("table.bulkDiscardValues", options);
|
|
3022
|
+
return postSelection(BULK_DISCARD_VALUES_PATH, selectors, options);
|
|
3027
3023
|
}
|
|
3028
3024
|
async function updateFromCsv(id, action, file, options) {
|
|
3029
3025
|
await transport.requestRaw(`/api/table/${id}/${UPLOAD_UPDATE_PATHS[action]}`, {
|
|
@@ -3065,7 +3061,11 @@ function tableResource(transport) {
|
|
|
3065
3061
|
fks,
|
|
3066
3062
|
syncSchema,
|
|
3067
3063
|
rescanValues,
|
|
3064
|
+
discardValues,
|
|
3068
3065
|
bulkEdit,
|
|
3066
|
+
bulkSyncSchema,
|
|
3067
|
+
bulkRescanValues,
|
|
3068
|
+
bulkDiscardValues,
|
|
3069
3069
|
appendCsv,
|
|
3070
3070
|
replaceCsv
|
|
3071
3071
|
};
|