@metabase/cli 0.4.1-alpha.fix-transform-test-ee-path.b41b46c → 0.5.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-CcjydN8e.mjs → add-collection-COtKcy6Y.mjs} +4 -4
- package/dist/{alert-DBTU8iHe.mjs → alert-DMlSjPEv.mjs} +7 -7
- package/dist/{alerts-DsgnumqY.mjs → alerts-s3al16NZ.mjs} +6 -6
- package/dist/{append-DUFn3_Og.mjs → append-CbGmdeLw.mjs} +4 -4
- package/dist/{archive-CWs273rN.mjs → archive-5EY9UJU_.mjs} +3 -3
- package/dist/{archive-Bxl1oeJr.mjs → archive-BFmx4B91.mjs} +3 -3
- package/dist/{archive-CcPTctIo.mjs → archive-BZCYIBhQ.mjs} +3 -3
- package/dist/{archive-sfqadV_a.mjs → archive-C_UHeanE.mjs} +3 -3
- package/dist/{archive-CC6THE3k.mjs → archive-Ce4eArrs.mjs} +3 -3
- package/dist/{archive-CI-WE7dA.mjs → archive-CnDriekB.mjs} +5 -5
- package/dist/{archive-DVgglC0F.mjs → archive-DDO2XX0E.mjs} +4 -4
- package/dist/{archive-DjQkD1WI.mjs → archive-DW7x0IFB.mjs} +4 -4
- package/dist/{archive-BEzfnrwM.mjs → archive-DvbaSglr.mjs} +3 -3
- package/dist/{archive-BTfOiOnx.mjs → archive-DzSdJVqE.mjs} +5 -5
- package/dist/{archive-jwyopr47.mjs → archive-a05W75XH.mjs} +3 -3
- package/dist/{auth-IQKgyb_x.mjs → auth-DOz7KW5E.mjs} +5 -5
- package/dist/{body-CT1cQrhp.mjs → body-Di7940x_.mjs} +2 -3
- package/dist/{branch-flag-Czh8JT1G.mjs → branch-flag-CfJ8vwgu.mjs} +1 -1
- package/dist/{branches-ByUeNOBP.mjs → branches-BC-vlk6i.mjs} +3 -3
- package/dist/{breaking-BKR88YVq.mjs → breaking-ByrjsFjq.mjs} +6 -6
- package/dist/{broken-DeS3_Cg2.mjs → broken-DLSk1T88.mjs} +8 -8
- package/dist/{bulk-discard-values-DY7svs0d.mjs → bulk-discard-values-VKGj8c7z.mjs} +5 -5
- package/dist/{bulk-edit-3EfcsqCu.mjs → bulk-edit-CpuleeCQ.mjs} +5 -5
- package/dist/{bulk-rescan-values-BpwnC_WY.mjs → bulk-rescan-values-DeGwiqLS.mjs} +5 -5
- package/dist/{bulk-sync-schema-Dwbs0TsG.mjs → bulk-sync-schema-BKVhauW1.mjs} +5 -5
- package/dist/{cancel-Nz4jJ-Ey.mjs → cancel-qKj45001.mjs} +3 -3
- package/dist/{cancel-task-CX_qYiJ0.mjs → cancel-task-nmBBd1Ky.mjs} +3 -3
- package/dist/card-Buc-X4Mh.mjs +25 -0
- package/dist/{cards-FUW8-5PO.mjs → cards-Bq73s48q.mjs} +4 -4
- package/dist/cli.mjs +628 -229
- package/dist/{client-5y-BaV3d.mjs → client-BmURNkkW.mjs} +997 -365
- package/dist/{collection-DPiztU_l.mjs → collection-C03LXnCT.mjs} +1 -1
- package/dist/collection-D-sS0AFw.mjs +21 -0
- package/dist/{collection-namespace-Q_up_tSg.mjs → collection-namespace-DaDzK31i.mjs} +1 -2
- package/dist/{collection-BgPYl2c5.mjs → collection-zrZoJfgR.mjs} +1 -1
- package/dist/{content-translation-CSkaKlqa.mjs → content-translation-BlG41YrA.mjs} +3 -3
- package/dist/{copy-WlNBviDZ.mjs → copy-DOKlVa7H.mjs} +6 -6
- package/dist/{copy-fikpWJO4.mjs → copy-DTiYs_a2.mjs} +4 -4
- package/dist/{copy-flags-j38p0var.mjs → copy-flags-BhGWC5kS.mjs} +2 -2
- package/dist/{create-C4dDHOzR.mjs → create-1rLk8b5q.mjs} +3 -3
- package/dist/{create-BmCz5lro.mjs → create-B1QDNU1x.mjs} +6 -6
- package/dist/{create-BI73JzZN.mjs → create-B1bX6ngX.mjs} +4 -4
- package/dist/{create-9sPJd45D.mjs → create-B5BwdPwT.mjs} +6 -6
- package/dist/{create-CC89lXeE.mjs → create-BKKNIe93.mjs} +3 -3
- package/dist/{create-COv2mYmk.mjs → create-BXX_n64u.mjs} +4 -4
- package/dist/{create-CEezFRTJ.mjs → create-BpwZJZxb.mjs} +5 -5
- package/dist/{create-DqGen4jU.mjs → create-C0kz0oYc.mjs} +3 -3
- package/dist/{create-CLLcjbzq.mjs → create-Cob0gLsA.mjs} +3 -3
- package/dist/{create-yLNBBrwG.mjs → create-DPggIXfn.mjs} +4 -4
- package/dist/{create-DdnC7PkI.mjs → create-DUytP2Y1.mjs} +4 -4
- package/dist/{create-CO6gBV7I.mjs → create-DraZzrLO.mjs} +4 -4
- package/dist/{create-Dp1597uC.mjs → create-Duj_2YIF.mjs} +4 -4
- package/dist/{create-C0MNevKK.mjs → create-JaFhqysM.mjs} +5 -5
- package/dist/{create-branch-Cflee_NY.mjs → create-branch-B5jB4tKk.mjs} +3 -3
- package/dist/{create-CYqqBKhE.mjs → create-d0trLAzB.mjs} +4 -4
- package/dist/{create-Ci7o6-Fk.mjs → create-vOw8gmBU.mjs} +3 -3
- package/dist/{csv-CX1wws5-.mjs → csv-DfExp9H_.mjs} +4 -4
- package/dist/{current-task-BTnORR7t.mjs → current-task-CbXIH_RA.mjs} +4 -4
- package/dist/dashboard-DH_soSQp.mjs +35 -0
- package/dist/{database-D-CRyRIv.mjs → database-BdKkae1m.mjs} +1 -1
- package/dist/{database-MlUPpitM.mjs → database-DoNoZ8Yc.mjs} +1 -1
- package/dist/{dataset-p5oNPQgL.mjs → dataset-DZgJm5hP.mjs} +3 -14
- package/dist/{db-DNevs1XU.mjs → db-C82M3Gpg.mjs} +7 -7
- package/dist/{delete-BJ18ifIG.mjs → delete-9xHRd2CG.mjs} +4 -4
- package/dist/{delete-dfrM_M6T.mjs → delete-B4BfGfiJ.mjs} +4 -4
- package/dist/{delete-D5Jy83V-.mjs → delete-D0xFMRRq.mjs} +4 -4
- package/dist/{delete-CCUYbNae.mjs → delete-DJ7SNXiH.mjs} +4 -4
- package/dist/{delete-ChmqxYa7.mjs → delete-hcw_4pBG.mjs} +4 -4
- package/dist/{delete-Ch797MmM.mjs → delete-hwPqKXeY.mjs} +4 -4
- package/dist/{delete-runtime-Cc7TASG7.mjs → delete-runtime-DkgYUQ_n.mjs} +1 -1
- package/dist/{delete-table-0xxoSknN.mjs → delete-table-DhTMft7u.mjs} +4 -4
- package/dist/{dependencies-GvzMLOS2.mjs → dependencies-B8H2gA04.mjs} +5 -5
- package/dist/dependency-CLznxtLE.mjs +15 -0
- package/dist/{dependency-BZxbh7qe.mjs → dependency-Dc33mjgd.mjs} +2 -2
- package/dist/{dependency-DaGeVAHF.mjs → dependency-tQBxYjFX.mjs} +1 -1
- package/dist/{dependents-BRqKb0Pu.mjs → dependents-B2GcS5kB.mjs} +9 -9
- package/dist/{dirty-Bq2cf5AG.mjs → dirty-Cz2rUd6S.mjs} +4 -4
- package/dist/{discard-values-k5-ePxWl.mjs → discard-values-QWuWGaVK.mjs} +5 -5
- package/dist/{document-COQzVLjW.mjs → document-BDobDiap.mjs} +1 -1
- package/dist/document-WhSEyI-3.mjs +20 -0
- package/dist/{document-BsaKF8UR.mjs → document-wfWbV0B_.mjs} +1 -1
- package/dist/{download-Dpbarf8I.mjs → download-Dw15fUMy.mjs} +2 -2
- package/dist/{eid-BEc1p_um.mjs → eid-Ex4G-ZlN.mjs} +4 -4
- package/dist/{entity-c_Br4SFc.mjs → entity-DBKPaMr5.mjs} +2 -2
- package/dist/{entry-flags-z8cZTfaQ.mjs → entry-flags-DgY3IXFe.mjs} +4 -4
- package/dist/{events-DBpOpy2y.mjs → events-BibJ4ya0.mjs} +4 -4
- package/dist/{export-F-R_vF48.mjs → export-U8MdaatW.mjs} +7 -7
- package/dist/{export-flags-QbLI0sKz.mjs → export-flags-BrfeyE8D.mjs} +2 -2
- package/dist/{export-preflight-0BvDa8Oz.mjs → export-preflight-A28L45au.mjs} +5 -5
- package/dist/field-qF1KRJYB.mjs +21 -0
- package/dist/{fields-DOdrazv2.mjs → fields-i1TFa_th.mjs} +4 -4
- package/dist/{filter-flags-DiUgZ6vZ.mjs → filter-flags-Bm3vuSM-.mjs} +3 -3
- package/dist/{fks-41Ig_ZQ2.mjs → fks-Dcfn3-73.mjs} +6 -6
- package/dist/{get-Dwp_BfIp.mjs → get-B4_3DID6.mjs} +5 -5
- package/dist/{get-TbBkN-jS.mjs → get-BCdtCwaG.mjs} +3 -3
- package/dist/{get-BVaN-tgY.mjs → get-BKDTRMNU.mjs} +3 -3
- package/dist/{get-CVJFF8Lb.mjs → get-BiPSePQc.mjs} +3 -3
- package/dist/{get-DaxwG0AP.mjs → get-C3ojRVJ_.mjs} +4 -4
- package/dist/{get-B8hREA2A.mjs → get-CCLWWqTD.mjs} +4 -4
- package/dist/{get-aC5jUA1y.mjs → get-CVpIQb8v.mjs} +5 -5
- package/dist/{get-BjJdy_Iw.mjs → get-CcwRn8Y2.mjs} +5 -5
- package/dist/{get-BAV-KpLU.mjs → get-CobILQ_7.mjs} +3 -3
- package/dist/{get-OKOOd2yb.mjs → get-Cwj1Q-at.mjs} +3 -3
- package/dist/{get-DwUB0K2G.mjs → get-D0NZ0ZO1.mjs} +3 -3
- package/dist/{get-2l2CbHc6.mjs → get-DPZUIPjv.mjs} +3 -3
- package/dist/{get-D1c-C-_Q2.mjs → get-DUwX-RU82.mjs} +3 -3
- package/dist/{get-Bby33eun.mjs → get-DqYn9mez.mjs} +4 -4
- package/dist/{get-CPhMYZDP.mjs → get-Dz3dNirC.mjs} +4 -4
- package/dist/{get-CfeNeyGE.mjs → get-EKBYludD.mjs} +3 -3
- package/dist/{get-YinpF0y5.mjs → get-HFQSttF3.mjs} +5 -5
- package/dist/{get-CjK2GzFn.mjs → get-IjoHBExI.mjs} +5 -5
- package/dist/{get-BlLUy1G0.mjs → get-hAoJtVCK.mjs} +3 -3
- package/dist/{get-run-PeXiUJwf.mjs → get-run-B2SnsZSY.mjs} +4 -4
- package/dist/git-sync-BlgB_-8-.mjs +29 -0
- package/dist/{git-sync-DspFahwV.mjs → git-sync-Ch1V1fEK.mjs} +1 -1
- package/dist/{glossary-CdW6RFId.mjs → glossary-6LLpItof.mjs} +1 -1
- package/dist/glossary-BvVxqjxJ.mjs +14 -0
- package/dist/{glossary-Del97Jqg.mjs → glossary-wnuxoE_I.mjs} +1 -1
- package/dist/{graph-M7V_js_w.mjs → graph-CHlfxVy1.mjs} +6 -6
- package/dist/{group-D4w87fXL.mjs → group-B3X3LTcU.mjs} +1 -1
- package/dist/{has-remote-changes-D7uABGR0.mjs → has-remote-changes-DCMpqGgE.mjs} +3 -3
- package/dist/{import-CABYSyWS.mjs → import-C7MZhKo6.mjs} +7 -7
- package/dist/{input-DjHsV-kD.mjs → input-sRdxNc3T.mjs} +1 -1
- package/dist/{is-dirty-DpQBXuVa.mjs → is-dirty-DpLyHebS.mjs} +2 -2
- package/dist/{items-BqUCPf-J.mjs → items-1ME_eg27.mjs} +6 -6
- package/dist/{key-BTaxFn_7.mjs → key-DMtgTOwN.mjs} +1 -1
- package/dist/{library-DmkpcZPb.mjs → library-CP-9yepy.mjs} +1 -1
- package/dist/{library-DDrpsgMv.mjs → library-D2ogEIfI.mjs} +5 -5
- package/dist/{library-C4M8TF2N.mjs → library-fWEv38OB.mjs} +2 -2
- package/dist/{list-Dd9o6Tut.mjs → list-B0h-j1E7.mjs} +3 -3
- package/dist/{list-ISpYiawJ.mjs → list-BUZ91ctZ.mjs} +5 -5
- package/dist/{list-CLRezReA.mjs → list-BUwDGyIu.mjs} +5 -5
- package/dist/{list-C9H24xr5.mjs → list-BXcDPU5d.mjs} +6 -6
- package/dist/{list-BQXq0A65.mjs → list-BoVeF8QA.mjs} +6 -6
- package/dist/{list-CHUwj_Qh.mjs → list-C1oEpUZG.mjs} +3 -3
- package/dist/{list-Hiq5T4Bt.mjs → list-C9996vbS.mjs} +3 -3
- package/dist/{list-DO767sO1.mjs → list-CJ5FyCnL.mjs} +4 -4
- package/dist/{list-BFAc460G.mjs → list-CQi3AgS5.mjs} +4 -4
- package/dist/{list-yDJq3wNs.mjs → list-CVh8DHOO.mjs} +5 -5
- package/dist/{list-D217irjK.mjs → list-DBAEy3Rx.mjs} +3 -3
- package/dist/{list-glgnTw7w.mjs → list-DkCadZ2E.mjs} +3 -3
- package/dist/{list-CEU9UXaZ.mjs → list-DzP7YXdZ.mjs} +3 -3
- package/dist/{list-aHFBopQd.mjs → list-LMlJ4uAY.mjs} +4 -4
- package/dist/{list-BXRUiZuH.mjs → list-NINy7ybI.mjs} +4 -4
- package/dist/{list-CONZkA9i.mjs → list-OXiXtdiM.mjs} +5 -5
- package/dist/{list-BygxQkq7.mjs → list-STy8UHs2.mjs} +6 -6
- package/dist/{list-CZF_gQnI.mjs → list-Ud7F0XdU.mjs} +3 -3
- package/dist/{list-D0MlsdSX.mjs → list-dCi6OaIE.mjs} +4 -4
- package/dist/{login-DCWam2ec.mjs → login-BMON3Fft.mjs} +6 -6
- package/dist/{logout-CmrJqhkc.mjs → logout-Cx934GzW.mjs} +2 -2
- package/dist/{measure-c_VUyXFN.mjs → measure-CUqJtDNm.mjs} +6 -6
- package/dist/{notification-Cuuwoksm.mjs → notification-CCZ9mrOw.mjs} +1 -1
- package/dist/{parameter-values-CnwWZrJ_.mjs → parameter-values-DCrU02Az.mjs} +3 -3
- package/dist/{parse-enum-BPKULOSw.mjs → parse-enum-Do5Cptbv.mjs} +1 -1
- package/dist/{parse-id-aMXePsUP.mjs → parse-id-oCbmouCn.mjs} +1 -1
- package/dist/{parse-ref-8bVX_9IN.mjs → parse-ref-Df8gusl4.mjs} +1 -1
- package/dist/{parse-text-Bm6eUa-p.mjs → parse-text-CVrP7GmZ.mjs} +1 -1
- package/dist/{path-CGbz-QSr.mjs → path-DTuSDGd6.mjs} +4 -4
- package/dist/{poll-DFZRtTA_.mjs → poll-BKo5dK0l.mjs} +2 -2
- package/dist/{preflight-ChJ0pemy.mjs → preflight-UeYuGDPr.mjs} +2 -3
- package/dist/{process-B3Di_HtV.mjs → process-BpmZXbcw.mjs} +1 -1
- package/dist/{publish-7ke00CtK.mjs → publish-D3GwLC-K.mjs} +4 -4
- package/dist/{pulse-CIza18rO.mjs → pulse-DzVPfb5J.mjs} +1 -1
- package/dist/{query-8M7ZN2Ca.mjs → query-B1Cp9EO6.mjs} +4 -4
- package/dist/{query-DNa-fGS7.mjs → query-Ct697cY-.mjs} +11 -12
- package/dist/{remapping-Cy1CEown.mjs → remapping-RsoPWE7c.mjs} +4 -4
- package/dist/{remove-collection-B2CL66No.mjs → remove-collection-BJo3Wd9K.mjs} +4 -4
- package/dist/{render-ColPG5G7.mjs → render-C_ev6qoW.mjs} +2 -2
- package/dist/{replace-COC3ggyx.mjs → replace-BSAGp3cR.mjs} +4 -4
- package/dist/requirement-check-T3bjQ0Mr.mjs +60 -0
- package/dist/{rescan-values-DUX58myu.mjs → rescan-values-CE62_2dc.mjs} +5 -5
- package/dist/{rescan-values-DXzXTw9a.mjs → rescan-values-rpro4Kw2.mjs} +5 -5
- package/dist/{run-C5wf-lug.mjs → run-B3BRodEp.mjs} +3 -3
- package/dist/{run-T2a4m1x9.mjs → run-BI1QO9Kn.mjs} +7 -7
- package/dist/{runs-Datc76Wu.mjs → runs-CUseZezf.mjs} +5 -5
- package/dist/{runtime-C3AL15Dp.mjs → runtime-C5Ha6Ou8.mjs} +248 -534
- package/dist/{schema-tables-CR2S5mNc.mjs → schema-tables-C7YkyRh0.mjs} +6 -6
- package/dist/{schemas-OrGjEuVc.mjs → schemas-Bj5sJ9uB.mjs} +4 -4
- package/dist/{search-BEXBlfak.mjs → search-BsAwK7Rk.mjs} +5 -5
- package/dist/{search-CJYSB5eP.mjs → search-CB1A4HWx.mjs} +6 -6
- package/dist/{segment-Tt8GaRnc.mjs → segment-BEjaeLc5.mjs} +6 -6
- package/dist/{send-uNLODakO.mjs → send-Dfh8d1gG.mjs} +3 -3
- package/dist/{set-DRp3F4wz.mjs → set-DA8dKyzi.mjs} +4 -4
- package/dist/{set-active-CAt6ieXS.mjs → set-active-AyjKtBD-.mjs} +3 -3
- package/dist/{set-sensitivity--Qq2RXVE.mjs → set-sensitivity-D0613dHA.mjs} +4 -4
- package/dist/{setting-DMqvipRp.mjs → setting-B-bxCkC0.mjs} +4 -4
- package/dist/{setup-B2PC1NVz.mjs → setup-Bvvqlz9d.mjs} +3 -3
- package/dist/{signal-0Yt8JTMn.mjs → signal-Dm4N0Bcc.mjs} +1 -1
- package/dist/{skill-list-Cyx1935Q.mjs → skill-list-DkuCf0k4.mjs} +9 -3
- package/dist/{skills-Dlp0MK6g.mjs → skills-DlDCTGVE.mjs} +2 -2
- package/dist/{skills-D7wu2iff.mjs → skills-DxrO7HUz.mjs} +3 -3
- package/dist/snippet-B7Kau5U8.mjs +19 -0
- package/dist/{stash-CHeQPI8Z.mjs → stash-j9JPv3ns.mjs} +5 -5
- package/dist/{status-Bdt5XWrQ.mjs → status-DcbvbRc5.mjs} +3 -3
- package/dist/{status-gTN3G-rs.mjs → status-DxNcrfnI.mjs} +16 -7
- package/dist/{subscription-C9alueg1.mjs → subscription-CSR2t-xK.mjs} +6 -6
- package/dist/{subscriptions-DJKbcxDy.mjs → subscriptions--0YvW40u.mjs} +6 -6
- package/dist/{summary-kaC0aINr.mjs → summary-Dslv78-r.mjs} +3 -3
- package/dist/{sync-schema-CyKovAb9.mjs → sync-schema-BSJiokQf.mjs} +6 -6
- package/dist/{sync-schema-C29bGCtt.mjs → sync-schema-Dgij5ICd.mjs} +5 -5
- package/dist/{sync-task-BAMOf6_t.mjs → sync-task-a1zyF1Qb.mjs} +4 -5
- package/dist/{table-BFIOH6Pb.mjs → table-Uvu1roSx.mjs} +2 -2
- package/dist/table-qjgz2eek.mjs +26 -0
- package/dist/{table-selector-flags-CSoedTgm.mjs → table-selector-flags-B9OiA3Z1.mjs} +3 -3
- package/dist/{table-Ci6bhZkb.mjs → table-zAdW5_3H.mjs} +5 -5
- package/dist/{text-CdtEI6l6.mjs → text-821Rn8M9.mjs} +1 -1
- package/dist/timeline-CNkrY3e3.mjs +21 -0
- package/dist/{timeline-event-DN3y8vwW.mjs → timeline-event-CSzx8EDP.mjs} +6 -6
- package/dist/{transform-D4z70PIN.mjs → transform-BKX6tl3i.mjs} +1 -1
- package/dist/transform-Y86R7_2F.mjs +28 -0
- package/dist/transform-job-Cg_1jzWI.mjs +22 -0
- package/dist/{transform-tag-CIKnNaQH.mjs → transform-tag-DHg7j15d.mjs} +5 -5
- package/dist/{transforms-BQjwZKTN.mjs → transforms-DwxPfMiG.mjs} +5 -5
- package/dist/{tree-C21CG5rm.mjs → tree-COFmA20J.mjs} +3 -3
- package/dist/{unpublish-C7MRZTmS.mjs → unpublish-BQClh4U7.mjs} +3 -3
- package/dist/{unreferenced-BJUIC_Ct.mjs → unreferenced-DKc0zZDl.mjs} +6 -6
- package/dist/{update-CuYvtXQY.mjs → update-B-wcIl8T.mjs} +4 -4
- package/dist/{update-DDH6FTe6.mjs → update-B8jQTspb.mjs} +8 -8
- package/dist/{update-9b4JHJWR.mjs → update-BBLbEPEP.mjs} +4 -4
- package/dist/{update-C0QcHFIP.mjs → update-BNwjjMk6.mjs} +5 -5
- package/dist/{update-BXFGGYT8.mjs → update-BVFfoopT.mjs} +5 -5
- package/dist/{update-CVO8Srng.mjs → update-BVMgrMy7.mjs} +5 -5
- package/dist/{update-CCHTQjsP.mjs → update-Bgy2amR0.mjs} +6 -6
- package/dist/{update-CYy-r_Jq.mjs → update-C9HK3i8s.mjs} +5 -5
- package/dist/{update-IEVAFvpi.mjs → update-CFfr1ZdL.mjs} +4 -4
- package/dist/{update-B2F22ryV.mjs → update-CMRWXoZ2.mjs} +4 -4
- package/dist/{update-D6oHLn1g.mjs → update-CPmPnEvm.mjs} +6 -6
- package/dist/{update-Duxk_-dC.mjs → update-Ca8LSZer.mjs} +5 -5
- package/dist/{update-CBcJTZo6.mjs → update-DJwu8UT2.mjs} +4 -4
- package/dist/{update-DX1s6KnO.mjs → update-Dwr3n7_n.mjs} +7 -7
- package/dist/{update-DEnsF5zT.mjs → update-MxvqmZ3z.mjs} +6 -6
- package/dist/{update-dashcard-C4ZndfvP.mjs → update-dashcard-C8QN2Qcu.mjs} +4 -4
- package/dist/{update-EpHReUGk.mjs → update-kM3TDlEp.mjs} +5 -5
- package/dist/{update-CZ2eSAV5.mjs → update-myfBF5qV.mjs} +4 -4
- package/dist/{upgrade-o2DpB66j.mjs → upgrade-BBOEVIRa.mjs} +4 -4
- package/dist/{upload-CEtKrueq.mjs → upload-CoBd4qBp.mjs} +3 -3
- package/dist/{upload-DJB7DMA1.mjs → upload-CxpXpjCf.mjs} +2 -2
- package/dist/upload-fcim1xtK.mjs +13 -0
- package/dist/{uuid-D9oozo8p.mjs → uuid-DW30GY7B.mjs} +2 -2
- package/dist/{validate-D_iikPkc.mjs → validate-n85yMraN.mjs} +1 -1
- package/dist/{validate-query-BEYjmSv2.mjs → validate-query-BwXvFFYi.mjs} +2 -2
- package/dist/{values-De8aGDiJ.mjs → values-B6eFE4K5.mjs} +3 -3
- package/dist/{verify-DVjaammv.mjs → verify-BSq7x66g.mjs} +3 -3
- package/dist/{verify-ob8JSLxv.mjs → verify-DnU-wXIs.mjs} +4 -4
- package/dist/{verify-DKmz4xJs.mjs → verify-Dp8tUbP3.mjs} +3 -3
- package/dist/{wait-BN_MzTng.mjs → wait-D6Tw4ZxO.mjs} +6 -6
- package/dist/{wait-flags-DQlX2yM_.mjs → wait-flags-BRUzMI6S.mjs} +2 -2
- package/dist/{window-2ybHqui2.mjs → window-BqMFpWMh.mjs} +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +5 -8
- package/skill-data/dashboard/SKILL.md +6 -0
- package/skill-data/git-sync/SKILL.md +64 -14
- package/skill-data/transform/SKILL.md +1 -63
- package/dist/card-DmQO85ej.mjs +0 -25
- package/dist/collection-BPVrTfTv.mjs +0 -21
- package/dist/create-DQM_AB3I.mjs +0 -34
- package/dist/dashboard-c_wOMtS9.mjs +0 -35
- package/dist/delete-CZTG4wI2.mjs +0 -44
- package/dist/dependency-D6DMbPVm.mjs +0 -15
- package/dist/document-DCqe5MO9.mjs +0 -20
- package/dist/field-CcCQ0goz.mjs +0 -21
- package/dist/get-DxpDAUz4.mjs +0 -32
- package/dist/git-sync-CO199xCu.mjs +0 -29
- package/dist/glossary-LdAlftZW.mjs +0 -14
- package/dist/list-CQJABPGk.mjs +0 -35
- package/dist/run-C_nqwWmC.mjs +0 -63
- package/dist/snippet-D-5bKT_U.mjs +0 -19
- package/dist/table-8c-V5afO.mjs +0 -26
- package/dist/timeline-BetOmLYk.mjs +0 -21
- package/dist/transform-job-DALBzYVV.mjs +0 -22
- package/dist/transform-p-6_thIh.mjs +0 -28
- package/dist/transform-test-BjjCQ2xm.mjs +0 -169
- package/dist/transform-test-C5Havg4o.mjs +0 -16
- package/dist/transform-test-DHGKeuHa.mjs +0 -32
- package/dist/transport-DuU3fLui.mjs +0 -313
- package/dist/update-BQben_Xm.mjs +0 -41
- package/dist/upload-BqNErDXE.mjs +0 -13
- package/skill-data/transform-test-plan/SKILL.md +0 -82
- package/skill-data/transform-test-plan/references/checklist.md +0 -32
- package/skill-data/transform-test-plan/references/checks.md +0 -156
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as setMetabaseAugment, A as consumeLegacyEnvWarnings, At as isNonInterruptFailure, B as evaluateFeatures, C as warn, Ct as ResponseShapeError, Dt as errorMessage, Et as ValidationError, G as isRetryableStatus, H as ruleGap, M as ProfileRefreshedError, Q as parseJsonResult, R as FEATURE_RULES, S as preflightUncheckedNotice, T as ENV_DISABLE_KEYRING, U as HttpError, Y as JSON_CONTENT_TYPE, ft as assertArgv, i as reportError, j as readEnv, jt as KNOWN_RANGE, k as ENV_URL, kt as isFileNotFoundError, mt as parseCsv, pt as givenFlagKeys, r as methodRequirements, t as interruptSignal, tt as version, vt as ConfigError, w as ENV_API_KEY, wt as TimeoutError, x as preflightSkippedNotice, xt as NetworkError, z as Features } from "./cli.mjs";
|
|
2
2
|
import { defineCommand } from "citty";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Entry } from "@napi-rs/keyring";
|
|
@@ -22,33 +22,6 @@ function parseOptionalInteger(value, options) {
|
|
|
22
22
|
return parseInteger(value, options);
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region ../client/src/version/preflight-error.ts
|
|
26
|
-
const RequirementReason = z.enum(["version-too-old", "missing-token-feature"]);
|
|
27
|
-
const RequirementFailure = z.object({
|
|
28
|
-
reason: RequirementReason,
|
|
29
|
-
detail: z.string(),
|
|
30
|
-
feature: z.enum(FEATURE_NAMES),
|
|
31
|
-
since: z.number().int(),
|
|
32
|
-
tokenFeature: z.string().nullable(),
|
|
33
|
-
serverVersion: z.string()
|
|
34
|
-
});
|
|
35
|
-
function versionTooOldMessage(since, serverVersion) {
|
|
36
|
-
return `This operation requires Metabase v${since}+ (this server is ${serverVersion}). Upgrade Metabase to use it.`;
|
|
37
|
-
}
|
|
38
|
-
function missingTokenFeatureMessage(tokenFeature) {
|
|
39
|
-
return `This operation requires the '${tokenFeature}' premium feature (not enabled on this server).`;
|
|
40
|
-
}
|
|
41
|
-
var CapabilityError = class extends MetabaseError {
|
|
42
|
-
category = "capability";
|
|
43
|
-
isRetryable = false;
|
|
44
|
-
developerDetail;
|
|
45
|
-
constructor(failure) {
|
|
46
|
-
super(failure.detail);
|
|
47
|
-
this.name = "CapabilityError";
|
|
48
|
-
this.developerDetail = failure;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
//#endregion
|
|
52
25
|
//#region ../client/src/domain/session-properties.ts
|
|
53
26
|
const ServerVersion$1 = z.object({
|
|
54
27
|
tag: z.string(),
|
|
@@ -111,26 +84,6 @@ function describeVersion(version) {
|
|
|
111
84
|
}
|
|
112
85
|
const StoredServerVersion = z.object({ tag: z.string() }).loose().transform(({ tag }) => parseTag(tag));
|
|
113
86
|
//#endregion
|
|
114
|
-
//#region ../client/src/version/probe.ts
|
|
115
|
-
const PROBE_PATH = "/api/session/properties";
|
|
116
|
-
const PROBE_TIMEOUT_MS = 1e4;
|
|
117
|
-
async function probeServer(client, opts = {}) {
|
|
118
|
-
return serverInfoFromProperties(await client.requestParsed(SessionProperties, PROBE_PATH, {
|
|
119
|
-
timeoutMs: PROBE_TIMEOUT_MS,
|
|
120
|
-
retries: opts.retries ?? 0
|
|
121
|
-
}));
|
|
122
|
-
}
|
|
123
|
-
function serverInfoFromProperties(properties) {
|
|
124
|
-
const { tag } = properties.version;
|
|
125
|
-
return {
|
|
126
|
-
version: parseTag(tag),
|
|
127
|
-
edition: editionFromTag(tag),
|
|
128
|
-
date: properties.version.date ?? null,
|
|
129
|
-
hash: properties.version.hash ?? null,
|
|
130
|
-
tokenFeatures: properties["token-features"] ?? null
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
//#endregion
|
|
134
87
|
//#region ../client/src/version/profile.ts
|
|
135
88
|
const Skew = z.enum([
|
|
136
89
|
"supported",
|
|
@@ -189,37 +142,6 @@ function grantsAnyFeature(tokenFeatures) {
|
|
|
189
142
|
return tokenFeatures !== null && Object.values(tokenFeatures).some((enabled) => enabled);
|
|
190
143
|
}
|
|
191
144
|
//#endregion
|
|
192
|
-
//#region ../client/src/version/requirement-check.ts
|
|
193
|
-
/** The first of `features` the profile lacks, or `null` when it has every one. */
|
|
194
|
-
function checkFeatures(features, profile) {
|
|
195
|
-
for (const feature of features) {
|
|
196
|
-
const gap = featureGap(profile, feature);
|
|
197
|
-
if (gap !== null) return describeGap(gap, feature, profile);
|
|
198
|
-
}
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
function describeGap(gap, feature, profile) {
|
|
202
|
-
const rule = FEATURE_RULES[feature];
|
|
203
|
-
const serverVersion = profile.version.tag;
|
|
204
|
-
const tokenFeature = rule.tokenFeature ?? null;
|
|
205
|
-
if (gap.kind === "token") return {
|
|
206
|
-
reason: "missing-token-feature",
|
|
207
|
-
detail: missingTokenFeatureMessage(gap.tokenFeature),
|
|
208
|
-
feature,
|
|
209
|
-
since: rule.since,
|
|
210
|
-
tokenFeature,
|
|
211
|
-
serverVersion
|
|
212
|
-
};
|
|
213
|
-
return {
|
|
214
|
-
reason: "version-too-old",
|
|
215
|
-
detail: versionTooOldMessage(rule.since, describeVersion(profile.version)),
|
|
216
|
-
feature,
|
|
217
|
-
since: rule.since,
|
|
218
|
-
tokenFeature,
|
|
219
|
-
serverVersion
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
//#endregion
|
|
223
145
|
//#region src/core/auth/server-summary.ts
|
|
224
146
|
const KnownRange = z.object({
|
|
225
147
|
min: z.number().int(),
|
|
@@ -257,17 +179,32 @@ function skewNotice(profile) {
|
|
|
257
179
|
switch (profile.skew) {
|
|
258
180
|
case "supported":
|
|
259
181
|
case "development": return null;
|
|
260
|
-
case "older-than-known": return `Metabase ${describeVersion(profile.version)} is older than this CLI supports (v${min}+);
|
|
182
|
+
case "older-than-known": return `Metabase ${describeVersion(profile.version)} is older than this CLI supports (v${min}+); a command relying on a newer feature may fail. Upgrade Metabase to v${min} or later.`;
|
|
261
183
|
case "newer-than-known": return `Metabase ${describeVersion(profile.version)} is newer than this CLI supports (up to v${max}); commands run as if it were v${max + 1}. Run \`mb upgrade\` for a newer CLI.`;
|
|
262
184
|
}
|
|
263
185
|
}
|
|
264
|
-
const
|
|
265
|
-
|
|
186
|
+
const PROFILE_REFRESHED = "the profile was refreshed";
|
|
187
|
+
const PROFILE_STALE = "the profile could not be updated (the warning above says why)";
|
|
188
|
+
const SAFE_METHODS = /* @__PURE__ */ new Set([
|
|
189
|
+
"GET",
|
|
190
|
+
"HEAD",
|
|
191
|
+
"OPTIONS"
|
|
192
|
+
]);
|
|
193
|
+
/** Whether two probes agree on everything a feature switch reads: the version tag and the premium features. */
|
|
194
|
+
function sameServer(a, b) {
|
|
195
|
+
return describeVersion(a.version) === describeVersion(b.version) && sameTokenFeatures(a.tokenFeatures, b.tokenFeatures);
|
|
196
|
+
}
|
|
197
|
+
function serverChangeNote(cached, fresh, method, profile) {
|
|
198
|
+
if (sameServer(cached, fresh)) return null;
|
|
199
|
+
const remedy = changeRemedy(SAFE_METHODS.has(method), profile);
|
|
266
200
|
const before = describeVersion(cached.version);
|
|
267
201
|
const after = describeVersion(fresh.version);
|
|
268
|
-
if (before !== after) return `The server's version changed since the last probe (was ${before}, now ${after}); ${
|
|
269
|
-
|
|
270
|
-
|
|
202
|
+
if (before !== after) return `The server's version changed since the last probe (was ${before}, now ${after}); ${remedy}`;
|
|
203
|
+
return `The server's premium features changed since the last probe; ${remedy}`;
|
|
204
|
+
}
|
|
205
|
+
function changeRemedy(isSafe, profile) {
|
|
206
|
+
if (profile === "current") return isSafe ? `${PROFILE_REFRESHED} — retry the command.` : `${PROFILE_REFRESHED}, but the request may have been applied — check before retrying.`;
|
|
207
|
+
return isSafe ? `${PROFILE_STALE} — retry the command once it can be.` : `${PROFILE_STALE}, and the request may have been applied — check before retrying.`;
|
|
271
208
|
}
|
|
272
209
|
function sameTokenFeatures(a, b) {
|
|
273
210
|
const grantedA = grantedFeatures(a);
|
|
@@ -369,296 +306,29 @@ function oauthCredentialFromTokens(tokens, refreshToken, clientId, nowMs) {
|
|
|
369
306
|
};
|
|
370
307
|
}
|
|
371
308
|
//#endregion
|
|
372
|
-
//#region ../client/src/
|
|
373
|
-
const
|
|
374
|
-
function
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
function parseJsonResult(input, schema, opts = {}) {
|
|
380
|
-
const sourcePrefix = opts.source === void 0 ? "" : `${opts.source}: `;
|
|
381
|
-
let raw;
|
|
382
|
-
try {
|
|
383
|
-
raw = JSON.parse(input);
|
|
384
|
-
} catch (error) {
|
|
385
|
-
return {
|
|
386
|
-
ok: false,
|
|
387
|
-
error: new ConfigError(`${sourcePrefix}invalid JSON: ${errorMessage(error)}`)
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
const parsed = schema.safeParse(raw);
|
|
391
|
-
if (!parsed.success) return {
|
|
392
|
-
ok: false,
|
|
393
|
-
error: new ValidationError(`${sourcePrefix}value did not match expected schema`, {
|
|
394
|
-
source: opts.source ?? "<input>",
|
|
395
|
-
zodIssues: parsed.error.issues
|
|
396
|
-
})
|
|
397
|
-
};
|
|
309
|
+
//#region ../client/src/version/probe.ts
|
|
310
|
+
const PROBE_PATH = "/api/session/properties";
|
|
311
|
+
async function probeServer(client, opts = {}) {
|
|
312
|
+
return serverInfoFromProperties(await client.requestParsed(SessionProperties, PROBE_PATH, probeBudget(opts)));
|
|
313
|
+
}
|
|
314
|
+
function probeBudget(opts) {
|
|
398
315
|
return {
|
|
399
|
-
|
|
400
|
-
|
|
316
|
+
timeoutMs: opts.timeoutMs ?? 1e4,
|
|
317
|
+
retries: opts.retries ?? 0
|
|
401
318
|
};
|
|
402
319
|
}
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
const attempt = parseJsonResult(text, schema, opts);
|
|
406
|
-
if (attempt.ok) return attempt.value;
|
|
407
|
-
if (attempt.error instanceof ValidationError) throw attempt.error;
|
|
408
|
-
return parseJson(JSON.stringify(text), schema, opts);
|
|
409
|
-
}
|
|
410
|
-
function isJsonContentType(contentType) {
|
|
411
|
-
return contentType !== null && contentType.includes("application/json");
|
|
412
|
-
}
|
|
413
|
-
//#endregion
|
|
414
|
-
//#region ../client/src/http/sanitize.ts
|
|
415
|
-
const SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
416
|
-
"authorization",
|
|
417
|
-
"x-api-key",
|
|
418
|
-
"x-metabase-session",
|
|
419
|
-
"cookie",
|
|
420
|
-
"set-cookie",
|
|
421
|
-
"proxy-authorization"
|
|
422
|
-
]);
|
|
423
|
-
const REDACTED = "[REDACTED]";
|
|
424
|
-
function redactHeaders(headers) {
|
|
425
|
-
const result = {};
|
|
426
|
-
const entries = headers instanceof Headers ? headers.entries() : Object.entries(headers);
|
|
427
|
-
for (const [key, value] of entries) result[key] = SECRET_HEADER_NAMES.has(key.toLowerCase()) ? REDACTED : value;
|
|
428
|
-
return result;
|
|
429
|
-
}
|
|
430
|
-
function redactBody(body, ctx) {
|
|
431
|
-
let result = body;
|
|
432
|
-
for (const secret of ctx.knownSecrets) {
|
|
433
|
-
if (secret.length === 0) continue;
|
|
434
|
-
result = result.replaceAll(secret, REDACTED);
|
|
435
|
-
}
|
|
436
|
-
return result;
|
|
437
|
-
}
|
|
438
|
-
//#endregion
|
|
439
|
-
//#region ../client/src/http/errors.ts
|
|
440
|
-
const NOT_FOUND_STATUS = 404;
|
|
441
|
-
const TEXT_CONTENT_TYPE = "text/plain";
|
|
442
|
-
const ROUTE_MISSING_LITERAL = "API endpoint does not exist.";
|
|
443
|
-
const RESOURCE_MISSING_LITERAL = "Not found.";
|
|
444
|
-
const STATUS_CLASSIFICATIONS = {
|
|
445
|
-
401: { retryable: false },
|
|
446
|
-
403: { retryable: false },
|
|
447
|
-
404: { retryable: false },
|
|
448
|
-
408: {
|
|
449
|
-
retryable: true,
|
|
450
|
-
message: "Metabase timed out responding."
|
|
451
|
-
},
|
|
452
|
-
425: { retryable: true },
|
|
453
|
-
429: {
|
|
454
|
-
retryable: true,
|
|
455
|
-
message: "Metabase rate-limited the request."
|
|
456
|
-
},
|
|
457
|
-
500: { retryable: true },
|
|
458
|
-
502: { retryable: true },
|
|
459
|
-
503: { retryable: true },
|
|
460
|
-
504: {
|
|
461
|
-
retryable: true,
|
|
462
|
-
message: "Metabase timed out responding."
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
const ErrorEnvelope = z.object({
|
|
466
|
-
message: z.string().optional(),
|
|
467
|
-
error: z.string().optional(),
|
|
468
|
-
"error-message": z.string().optional(),
|
|
469
|
-
via: z.array(z.object({ message: z.string().optional() }).loose()).optional(),
|
|
470
|
-
"specific-errors": z.unknown().optional(),
|
|
471
|
-
errors: z.unknown().optional(),
|
|
472
|
-
"error-code": z.string().optional()
|
|
473
|
-
}).loose();
|
|
474
|
-
const FieldErrorNodeSchema = z.lazy(() => z.union([
|
|
475
|
-
z.string(),
|
|
476
|
-
z.array(z.string()),
|
|
477
|
-
z.record(z.string(), FieldErrorNodeSchema)
|
|
478
|
-
]));
|
|
479
|
-
const FieldErrorTree = z.record(z.string(), FieldErrorNodeSchema);
|
|
480
|
-
const FIELD_MESSAGE_SEPARATOR = "; ";
|
|
481
|
-
const MAX_EXTRACTED_MESSAGE_LEN = 500;
|
|
482
|
-
const ELLIPSIS = "…";
|
|
483
|
-
const GOT_VALUE_PATTERN = /got: ((?:[^"\\]|\\.)*)/g;
|
|
484
|
-
const MAX_GOT_VALUE_LEN = 60;
|
|
485
|
-
var HttpError = class extends MetabaseError {
|
|
486
|
-
category = "http";
|
|
487
|
-
status;
|
|
488
|
-
kind;
|
|
489
|
-
developerDetail;
|
|
490
|
-
constructor(input) {
|
|
491
|
-
const sanitizedBody = sanitizeBody(input.rawBody, input.redactionContext);
|
|
492
|
-
const redactedHeaders = redactHeaders(input.responseHeaders);
|
|
493
|
-
const kind = classifyKind(input.status, sanitizedBody, redactedHeaders);
|
|
494
|
-
super(input.overrideUserMessage ?? buildUserMessage(kind, input, sanitizedBody, redactedHeaders));
|
|
495
|
-
const fields = extractEnvelopeViews(sanitizedBody);
|
|
496
|
-
this.name = "HttpError";
|
|
497
|
-
this.status = input.status;
|
|
498
|
-
this.kind = kind;
|
|
499
|
-
this.developerDetail = {
|
|
500
|
-
status: input.status,
|
|
501
|
-
statusText: input.statusText,
|
|
502
|
-
method: input.method,
|
|
503
|
-
url: input.url,
|
|
504
|
-
responseHeaders: redactedHeaders,
|
|
505
|
-
body: sanitizedBody,
|
|
506
|
-
fieldErrors: fields.fieldErrors,
|
|
507
|
-
specificFieldErrors: fields.specificFieldErrors,
|
|
508
|
-
errorCode: fields.errorCode
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
get isRetryable() {
|
|
512
|
-
return isRetryableStatus(this.status);
|
|
513
|
-
}
|
|
514
|
-
get fieldErrors() {
|
|
515
|
-
return this.developerDetail.fieldErrors;
|
|
516
|
-
}
|
|
517
|
-
get specificFieldErrors() {
|
|
518
|
-
return this.developerDetail.specificFieldErrors;
|
|
519
|
-
}
|
|
520
|
-
get errorCode() {
|
|
521
|
-
return this.developerDetail.errorCode;
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
function chainRequestFailure(cause, message) {
|
|
525
|
-
if (cause instanceof HttpError) return new HttpError({
|
|
526
|
-
status: cause.status,
|
|
527
|
-
statusText: cause.developerDetail.statusText,
|
|
528
|
-
method: cause.developerDetail.method,
|
|
529
|
-
url: cause.developerDetail.url,
|
|
530
|
-
responseHeaders: cause.developerDetail.responseHeaders,
|
|
531
|
-
rawBody: cause.developerDetail.body,
|
|
532
|
-
overrideUserMessage: message
|
|
533
|
-
});
|
|
534
|
-
return new ChainedRequestError(message, cause);
|
|
535
|
-
}
|
|
536
|
-
function isRetryableStatus(status) {
|
|
537
|
-
return STATUS_CLASSIFICATIONS[status]?.retryable === true;
|
|
538
|
-
}
|
|
539
|
-
function sanitizeBody(rawBody, ctx) {
|
|
540
|
-
if (rawBody === null) return null;
|
|
541
|
-
if (ctx === void 0) return rawBody;
|
|
542
|
-
return redactBody(rawBody, ctx);
|
|
543
|
-
}
|
|
544
|
-
function classifyKind(status, sanitizedBody, redactedHeaders) {
|
|
545
|
-
if (status === 401 || status === 403) return "auth";
|
|
546
|
-
if (status === NOT_FOUND_STATUS) return isRouteMissingResponse(sanitizedBody, redactedHeaders) ? "route-missing" : "resource-missing";
|
|
547
|
-
if (status === 429) return "rate-limit";
|
|
548
|
-
if (status >= 500 && status < 600) return "server-error";
|
|
549
|
-
return "generic";
|
|
550
|
-
}
|
|
551
|
-
function isRouteMissingResponse(sanitizedBody, redactedHeaders) {
|
|
552
|
-
if (sanitizedBody?.includes(ROUTE_MISSING_LITERAL)) return true;
|
|
553
|
-
if (sanitizedBody?.includes(RESOURCE_MISSING_LITERAL)) return false;
|
|
554
|
-
if (redactedHeaders["content-type"]?.includes("application/json")) return false;
|
|
555
|
-
if (sanitizedBody === null || sanitizedBody.trim() === "") return true;
|
|
556
|
-
return parseEnvelope(sanitizedBody) === null;
|
|
557
|
-
}
|
|
558
|
-
function buildUserMessage(kind, input, sanitizedBody, redactedHeaders) {
|
|
559
|
-
if (kind === "route-missing") return buildRouteMissingMessage(input);
|
|
560
|
-
if (kind === "resource-missing") return `Not found: ${input.method} ${pathFromUrl(input.url)}.`;
|
|
561
|
-
const fromBody = parseEnvelopeMessage(sanitizedBody);
|
|
562
|
-
if (fromBody !== null) return fromBody;
|
|
563
|
-
if (kind === "auth") return `Invalid or unauthorized API key (host: ${hostFromUrl(input.url)}).`;
|
|
564
|
-
const fromText = plainTextMessage(sanitizedBody, redactedHeaders);
|
|
565
|
-
if (fromText !== null) return fromText;
|
|
566
|
-
return defaultMessageForStatus(input.status);
|
|
567
|
-
}
|
|
568
|
-
function plainTextMessage(sanitizedBody, redactedHeaders) {
|
|
569
|
-
if (sanitizedBody === null || !redactedHeaders["content-type"]?.includes(TEXT_CONTENT_TYPE)) return null;
|
|
570
|
-
const trimmed = sanitizedBody.trim();
|
|
571
|
-
return trimmed === "" ? null : condenseMessage(trimmed);
|
|
572
|
-
}
|
|
573
|
-
function buildRouteMissingMessage(input) {
|
|
574
|
-
const path = pathFromUrl(input.url);
|
|
575
|
-
if (!input.serverTag) return `This endpoint is not available on the connected Metabase: ${input.method} ${path}.`;
|
|
576
|
-
return `This endpoint is not available on Metabase ${input.serverTag}: ${input.method} ${path}. It may require a newer Metabase major version.`;
|
|
577
|
-
}
|
|
578
|
-
function pathFromUrl(url) {
|
|
579
|
-
const parsed = new URL(url);
|
|
580
|
-
return parsed.pathname + parsed.search;
|
|
581
|
-
}
|
|
582
|
-
function hostFromUrl(url) {
|
|
583
|
-
return new URL(url).host;
|
|
584
|
-
}
|
|
585
|
-
function parseEnvelope(sanitizedBody) {
|
|
586
|
-
if (!sanitizedBody) return null;
|
|
587
|
-
const result = parseJsonResult(sanitizedBody, ErrorEnvelope);
|
|
588
|
-
return result.ok ? result.value : null;
|
|
589
|
-
}
|
|
590
|
-
const NO_ENVELOPE_VIEWS = {
|
|
591
|
-
fieldErrors: null,
|
|
592
|
-
specificFieldErrors: null,
|
|
593
|
-
errorCode: null
|
|
594
|
-
};
|
|
595
|
-
function extractEnvelopeViews(sanitizedBody) {
|
|
596
|
-
const envelope = parseEnvelope(sanitizedBody);
|
|
597
|
-
if (envelope === null) return NO_ENVELOPE_VIEWS;
|
|
320
|
+
function serverInfoFromProperties(properties) {
|
|
321
|
+
const { tag } = properties.version;
|
|
598
322
|
return {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
323
|
+
version: parseTag(tag),
|
|
324
|
+
edition: editionFromTag(tag),
|
|
325
|
+
date: properties.version.date ?? null,
|
|
326
|
+
hash: properties.version.hash ?? null,
|
|
327
|
+
tokenFeatures: properties["token-features"] ?? null
|
|
602
328
|
};
|
|
603
329
|
}
|
|
604
|
-
function
|
|
605
|
-
|
|
606
|
-
if (!parsed.success) return null;
|
|
607
|
-
const entries = collectLeafEntries(parsed.data, []);
|
|
608
|
-
if (entries.length === 0) return null;
|
|
609
|
-
return Object.fromEntries(entries.map((entry) => [entry.path, entry.message]));
|
|
610
|
-
}
|
|
611
|
-
function parseEnvelopeMessage(sanitizedBody) {
|
|
612
|
-
const envelope = parseEnvelope(sanitizedBody);
|
|
613
|
-
if (envelope === null) return null;
|
|
614
|
-
const topLevel = envelope.message ?? envelope.error ?? envelope["error-message"];
|
|
615
|
-
if (topLevel) return condenseMessage(topLevel);
|
|
616
|
-
const viaMessage = envelope.via?.find((entry) => entry.message)?.message;
|
|
617
|
-
if (viaMessage) return condenseMessage(viaMessage);
|
|
618
|
-
const specific = formatErrorTree(envelope["specific-errors"]);
|
|
619
|
-
if (specific) return condenseMessage(specific);
|
|
620
|
-
const generic = formatErrorTree(envelope.errors);
|
|
621
|
-
if (generic) return condenseMessage(generic);
|
|
622
|
-
return null;
|
|
623
|
-
}
|
|
624
|
-
function formatErrorTree(value) {
|
|
625
|
-
const entries = collectLeafEntries(value, []);
|
|
626
|
-
if (entries.length === 0) return null;
|
|
627
|
-
return entries.map(formatLeafEntry).join(FIELD_MESSAGE_SEPARATOR);
|
|
628
|
-
}
|
|
629
|
-
function formatLeafEntry(entry) {
|
|
630
|
-
return entry.path === "" ? entry.message : `${entry.path}: ${entry.message}`;
|
|
631
|
-
}
|
|
632
|
-
function collectLeafEntries(value, path) {
|
|
633
|
-
if (typeof value === "string") {
|
|
634
|
-
const trimmed = value.trim();
|
|
635
|
-
return trimmed === "" ? [] : [{
|
|
636
|
-
path: path.join("."),
|
|
637
|
-
message: trimmed
|
|
638
|
-
}];
|
|
639
|
-
}
|
|
640
|
-
if (Array.isArray(value)) {
|
|
641
|
-
const messages = value.filter((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
642
|
-
if (messages.length === 0) return [];
|
|
643
|
-
return [{
|
|
644
|
-
path: path.join("."),
|
|
645
|
-
message: messages.join(FIELD_MESSAGE_SEPARATOR)
|
|
646
|
-
}];
|
|
647
|
-
}
|
|
648
|
-
if (isPlainObject(value)) return Object.entries(value).flatMap(([key, child]) => collectLeafEntries(child, [...path, key]));
|
|
649
|
-
return [];
|
|
650
|
-
}
|
|
651
|
-
function condenseMessage(message) {
|
|
652
|
-
const trimmed = message.replace(GOT_VALUE_PATTERN, trimGotValue);
|
|
653
|
-
if (trimmed.length <= MAX_EXTRACTED_MESSAGE_LEN) return trimmed;
|
|
654
|
-
return trimmed.slice(0, MAX_EXTRACTED_MESSAGE_LEN - 1) + ELLIPSIS;
|
|
655
|
-
}
|
|
656
|
-
function trimGotValue(match, value) {
|
|
657
|
-
if (value.length <= MAX_GOT_VALUE_LEN) return match;
|
|
658
|
-
return `got: ${value.slice(0, MAX_GOT_VALUE_LEN)}${ELLIPSIS}`;
|
|
659
|
-
}
|
|
660
|
-
function defaultMessageForStatus(status) {
|
|
661
|
-
return STATUS_CLASSIFICATIONS[status]?.message ?? `Metabase returned ${status}.`;
|
|
330
|
+
function profileFromProperties(properties) {
|
|
331
|
+
return createServerProfile(serverInfoFromProperties(properties));
|
|
662
332
|
}
|
|
663
333
|
//#endregion
|
|
664
334
|
//#region ../client/src/http/network-error.ts
|
|
@@ -842,7 +512,7 @@ async function grantsFullAccessScope(metadata, baseUrl, userAgent) {
|
|
|
842
512
|
headers: { accept: JSON_CONTENT_TYPE }
|
|
843
513
|
});
|
|
844
514
|
if (!response.ok) throw await failure(response, "Server properties", "GET", url);
|
|
845
|
-
return createServerProfile(serverInfoFromProperties(await readJson(response, SessionProperties, "Server properties"))).features.
|
|
515
|
+
return createServerProfile(serverInfoFromProperties(await readJson(response, SessionProperties, "Server properties"))).features.oauthFullAccessScopeUnadvertised;
|
|
846
516
|
}
|
|
847
517
|
async function tryDiscoverMetadata(baseUrl, userAgent) {
|
|
848
518
|
const metadata = await fetchMetadata(baseUrl, userAgent);
|
|
@@ -1095,6 +765,12 @@ async function fileExists(path) {
|
|
|
1095
765
|
return false;
|
|
1096
766
|
}
|
|
1097
767
|
}
|
|
768
|
+
let profilesFileQueue = Promise.resolve();
|
|
769
|
+
function exclusively(update) {
|
|
770
|
+
const result = profilesFileQueue.then(update);
|
|
771
|
+
profilesFileQueue = result.then(() => void 0, () => void 0);
|
|
772
|
+
return result;
|
|
773
|
+
}
|
|
1098
774
|
async function writeProfilesFile(file) {
|
|
1099
775
|
const path = profilesFilePath();
|
|
1100
776
|
if (file.profiles.length === 0) {
|
|
@@ -1199,123 +875,130 @@ async function upsertRecord(file, name, updated) {
|
|
|
1199
875
|
});
|
|
1200
876
|
}
|
|
1201
877
|
async function writeProfile(profile, name = DEFAULT_PROFILE) {
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
name,
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
878
|
+
return exclusively(async () => {
|
|
879
|
+
const location = persistSecret(account.profileApiKey(name), profile.apiKey);
|
|
880
|
+
const inlineApiKey = location.backend === "file" ? profile.apiKey : null;
|
|
881
|
+
const file = await readProfilesFile();
|
|
882
|
+
const existing = findRecord(file, name);
|
|
883
|
+
flagResidualIfUnconfirmed(existing, "oauth", [removeKeyringEntry(account.profileOAuthAccess(name)), removeKeyringEntry(account.profileOAuthRefresh(name))]);
|
|
884
|
+
await upsertRecord(file, name, existing === null ? {
|
|
885
|
+
name,
|
|
886
|
+
url: profile.url,
|
|
887
|
+
apiKey: inlineApiKey,
|
|
888
|
+
oauth: null,
|
|
889
|
+
lastProbe: null,
|
|
890
|
+
lastFailure: null
|
|
891
|
+
} : {
|
|
892
|
+
...existing,
|
|
893
|
+
url: profile.url,
|
|
894
|
+
apiKey: inlineApiKey,
|
|
895
|
+
oauth: null
|
|
896
|
+
});
|
|
897
|
+
return location;
|
|
1219
898
|
});
|
|
1220
|
-
return location;
|
|
1221
899
|
}
|
|
1222
900
|
async function writeOAuthProfile(url, credential, name = DEFAULT_PROFILE) {
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
name,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
901
|
+
return exclusively(async () => {
|
|
902
|
+
const accessKey = account.profileOAuthAccess(name);
|
|
903
|
+
const refreshKey = account.profileOAuthRefresh(name);
|
|
904
|
+
const accessLocation = persistSecret(accessKey, credential.accessToken);
|
|
905
|
+
const refreshLocation = persistSecret(refreshKey, credential.refreshToken);
|
|
906
|
+
const onFile = accessLocation.backend === "file" || refreshLocation.backend === "file";
|
|
907
|
+
const oauth = {
|
|
908
|
+
accessToken: onFile ? credential.accessToken : null,
|
|
909
|
+
refreshToken: onFile ? credential.refreshToken : null,
|
|
910
|
+
expiresAt: credential.expiresAt,
|
|
911
|
+
clientId: credential.clientId
|
|
912
|
+
};
|
|
913
|
+
const file = await readProfilesFile();
|
|
914
|
+
const existing = findRecord(file, name);
|
|
915
|
+
if (onFile && existing !== null && sideIsKeyringBacked(existing, "oauth")) keyringDowngradeNotice = keyringFallbackWarning(fileLocation(accessKey));
|
|
916
|
+
flagResidualIfUnconfirmed(existing, "apiKey", [removeKeyringEntry(account.profileApiKey(name))]);
|
|
917
|
+
await upsertRecord(file, name, existing === null ? {
|
|
918
|
+
name,
|
|
919
|
+
url,
|
|
920
|
+
apiKey: null,
|
|
921
|
+
oauth,
|
|
922
|
+
lastProbe: null,
|
|
923
|
+
lastFailure: null
|
|
924
|
+
} : {
|
|
925
|
+
...existing,
|
|
926
|
+
url,
|
|
927
|
+
apiKey: null,
|
|
928
|
+
oauth
|
|
929
|
+
});
|
|
930
|
+
return onFile ? fileLocation(accessKey) : {
|
|
931
|
+
backend: "keyring",
|
|
932
|
+
service: KEYRING_SERVICE,
|
|
933
|
+
account: accessKey
|
|
934
|
+
};
|
|
1250
935
|
});
|
|
1251
|
-
return onFile ? fileLocation(accessKey) : {
|
|
1252
|
-
backend: "keyring",
|
|
1253
|
-
service: KEYRING_SERVICE,
|
|
1254
|
-
account: accessKey
|
|
1255
|
-
};
|
|
1256
936
|
}
|
|
1257
937
|
async function writeProbeResult(name, input) {
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
938
|
+
return exclusively(async () => {
|
|
939
|
+
const probe = ProfileLastProbe.parse({
|
|
940
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
941
|
+
version: input.server.version,
|
|
942
|
+
edition: input.server.edition,
|
|
943
|
+
date: input.server.date,
|
|
944
|
+
hash: input.server.hash,
|
|
945
|
+
tokenFeatures: input.server.tokenFeatures,
|
|
946
|
+
user: input.user
|
|
947
|
+
});
|
|
948
|
+
const file = await readProfilesFile();
|
|
949
|
+
if (findRecord(file, name) === null) return null;
|
|
950
|
+
const profiles = file.profiles.map((entry) => entry.name === name ? {
|
|
951
|
+
...entry,
|
|
952
|
+
lastProbe: probe,
|
|
953
|
+
lastFailure: null
|
|
954
|
+
} : entry);
|
|
955
|
+
await writeProfilesFile({
|
|
956
|
+
...file,
|
|
957
|
+
profiles
|
|
958
|
+
});
|
|
959
|
+
return probe;
|
|
1277
960
|
});
|
|
1278
|
-
return probe;
|
|
1279
961
|
}
|
|
1280
962
|
async function writeProbeFailure(name, input) {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
963
|
+
return exclusively(async () => {
|
|
964
|
+
const failure = ProfileLastFailure.parse({
|
|
965
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
966
|
+
kind: input.kind,
|
|
967
|
+
reason: input.reason
|
|
968
|
+
});
|
|
969
|
+
const file = await readProfilesFile();
|
|
970
|
+
if (findRecord(file, name) === null) return null;
|
|
971
|
+
const profiles = file.profiles.map((entry) => entry.name === name ? {
|
|
972
|
+
...entry,
|
|
973
|
+
lastFailure: failure
|
|
974
|
+
} : entry);
|
|
975
|
+
await writeProfilesFile({
|
|
976
|
+
...file,
|
|
977
|
+
profiles
|
|
978
|
+
});
|
|
979
|
+
return failure;
|
|
1295
980
|
});
|
|
1296
|
-
return failure;
|
|
1297
981
|
}
|
|
1298
982
|
async function clearProfile(name = DEFAULT_PROFILE) {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
983
|
+
return exclusively(async () => {
|
|
984
|
+
const file = await readProfilesFile();
|
|
985
|
+
const existing = findRecord(file, name);
|
|
986
|
+
const removals = [
|
|
987
|
+
removeKeyringEntry(account.profileApiKey(name)),
|
|
988
|
+
removeKeyringEntry(account.profileOAuthAccess(name)),
|
|
989
|
+
removeKeyringEntry(account.profileOAuthRefresh(name))
|
|
990
|
+
];
|
|
991
|
+
if (existing !== null) flagResidualIfUnconfirmed(existing, existing.oauth !== null ? "oauth" : "apiKey", removals);
|
|
992
|
+
if (existing === null) return false;
|
|
993
|
+
await writeProfilesFile({
|
|
994
|
+
...file,
|
|
995
|
+
profiles: file.profiles.filter((entry) => entry.name !== name)
|
|
996
|
+
});
|
|
997
|
+
return true;
|
|
1311
998
|
});
|
|
1312
|
-
return true;
|
|
1313
999
|
}
|
|
1314
1000
|
//#endregion
|
|
1315
1001
|
//#region src/core/config.ts
|
|
1316
|
-
function isPreflightSkipped() {
|
|
1317
|
-
return readEnv(ENV_SKIP_PREFLIGHT) === "1";
|
|
1318
|
-
}
|
|
1319
1002
|
function resolveProfileName(profileFlag) {
|
|
1320
1003
|
return explicitProfileName(profileFlag) ?? "default";
|
|
1321
1004
|
}
|
|
@@ -1451,7 +1134,8 @@ async function readCachedServerProfile(profileName) {
|
|
|
1451
1134
|
if (hit.kind !== "found") return hit;
|
|
1452
1135
|
return {
|
|
1453
1136
|
kind: "found",
|
|
1454
|
-
profile: createServerProfile(hit.probe)
|
|
1137
|
+
profile: createServerProfile(hit.probe),
|
|
1138
|
+
probedAt: hit.probe.at
|
|
1455
1139
|
};
|
|
1456
1140
|
}
|
|
1457
1141
|
//#endregion
|
|
@@ -1487,7 +1171,7 @@ function resolveCommonFlags(args, options = {}) {
|
|
|
1487
1171
|
url: args.url,
|
|
1488
1172
|
apiKey: args.apiKey,
|
|
1489
1173
|
profile: args.profile,
|
|
1490
|
-
skipPreflight: args.skipPreflight
|
|
1174
|
+
skipPreflight: args.skipPreflight
|
|
1491
1175
|
};
|
|
1492
1176
|
}
|
|
1493
1177
|
function parseFields(value) {
|
|
@@ -1529,45 +1213,42 @@ function defineMetabaseCommand(def) {
|
|
|
1529
1213
|
assertArgv(rawArgs, def.args);
|
|
1530
1214
|
const ctx = resolveCommonFlags(commonArgs);
|
|
1531
1215
|
let cachedConfig = null;
|
|
1532
|
-
let cachedClient = null;
|
|
1533
1216
|
const getResolvedConfig = async () => {
|
|
1534
1217
|
if (cachedConfig === null) cachedConfig = await resolveConfig(buildConfigFlags(ctx));
|
|
1535
1218
|
return cachedConfig;
|
|
1536
1219
|
};
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
const rawGetClient = async () => {
|
|
1541
|
-
if (cachedClient === null) {
|
|
1542
|
-
const resolved = await getResolvedConfig();
|
|
1543
|
-
const probe = await readCachedProbe(resolved.profile, resolved.url);
|
|
1544
|
-
const server = probe === null ? null : createServerProfile(probe);
|
|
1545
|
-
const { createClient } = await import("./client-5y-BaV3d.mjs").then((n) => n.t);
|
|
1546
|
-
cachedClient = createClient({
|
|
1547
|
-
url: resolved.url,
|
|
1548
|
-
credential: resolved.credential
|
|
1549
|
-
}, {
|
|
1550
|
-
userAgent: USER_AGENT,
|
|
1551
|
-
...server !== null && { server },
|
|
1552
|
-
refreshCredential: createCredentialRefresher(resolved.profile),
|
|
1553
|
-
signal: interruptSignal,
|
|
1554
|
-
enforceRequirements: !preflightSkipped
|
|
1555
|
-
});
|
|
1556
|
-
if (probe !== null && server !== null) {
|
|
1557
|
-
cachedServer = {
|
|
1558
|
-
client: cachedClient,
|
|
1559
|
-
profileName: resolved.profile,
|
|
1560
|
-
probe
|
|
1561
|
-
};
|
|
1562
|
-
noticeSkew(server);
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
return cachedClient;
|
|
1220
|
+
const run = {
|
|
1221
|
+
server: null,
|
|
1222
|
+
profileSave: Promise.resolve("current")
|
|
1566
1223
|
};
|
|
1567
|
-
const
|
|
1224
|
+
const noticeSkew = createSkewNotifier();
|
|
1225
|
+
const skipPreflight = ctx.skipPreflight ?? readEnv("MB_CLI_SKIP_PREFLIGHT") === "1";
|
|
1568
1226
|
const getClient = async () => {
|
|
1569
|
-
|
|
1570
|
-
await
|
|
1227
|
+
if (run.server !== null) return run.server.client;
|
|
1228
|
+
const resolved = await getResolvedConfig();
|
|
1229
|
+
const probe = await readCachedProbe(resolved.profile, resolved.url);
|
|
1230
|
+
const server = probe === null ? null : createServerProfile(probe);
|
|
1231
|
+
const saveProbe = probe === null ? null : createProbeSaver(resolved.profile, probe);
|
|
1232
|
+
const { createClient } = await import("./client-BmURNkkW.mjs").then((n) => n.t);
|
|
1233
|
+
const client = createClient({
|
|
1234
|
+
url: resolved.url,
|
|
1235
|
+
credential: resolved.credential
|
|
1236
|
+
}, {
|
|
1237
|
+
userAgent: USER_AGENT,
|
|
1238
|
+
...server !== null && { server },
|
|
1239
|
+
refreshCredential: createCredentialRefresher(resolved.profile),
|
|
1240
|
+
onServerProbed: (fresh, profile) => {
|
|
1241
|
+
noticeSkew(profile);
|
|
1242
|
+
if (saveProbe !== null) run.profileSave = run.profileSave.then(() => saveProbe(fresh));
|
|
1243
|
+
},
|
|
1244
|
+
...skipPreflight && { onPreflightSkipped: createPreflightSkipWarner() },
|
|
1245
|
+
signal: interruptSignal
|
|
1246
|
+
});
|
|
1247
|
+
run.server = {
|
|
1248
|
+
client,
|
|
1249
|
+
cachedProbe: probe
|
|
1250
|
+
};
|
|
1251
|
+
if (server !== null) noticeSkew(server);
|
|
1571
1252
|
return client;
|
|
1572
1253
|
};
|
|
1573
1254
|
try {
|
|
@@ -1578,8 +1259,9 @@ function defineMetabaseCommand(def) {
|
|
|
1578
1259
|
getResolvedConfig
|
|
1579
1260
|
});
|
|
1580
1261
|
} catch (error) {
|
|
1581
|
-
throw await
|
|
1262
|
+
throw await diagnoseFailure(error, run);
|
|
1582
1263
|
} finally {
|
|
1264
|
+
await settleRun(run);
|
|
1583
1265
|
emitPendingWarnings();
|
|
1584
1266
|
}
|
|
1585
1267
|
} catch (error) {
|
|
@@ -1619,40 +1301,72 @@ function createSkewNotifier() {
|
|
|
1619
1301
|
if (notice !== null) warn(notice);
|
|
1620
1302
|
};
|
|
1621
1303
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
if (
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1304
|
+
function createPreflightSkipWarner() {
|
|
1305
|
+
const warned = /* @__PURE__ */ new Set();
|
|
1306
|
+
return (skipped) => {
|
|
1307
|
+
const notice = skippedPreflightNotice(skipped);
|
|
1308
|
+
const key = skipped.kind === "unverified" ? skipped.kind : notice;
|
|
1309
|
+
if (warned.has(key)) return;
|
|
1310
|
+
warned.add(key);
|
|
1311
|
+
warn(notice);
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
function skippedPreflightNotice(skipped) {
|
|
1315
|
+
if (skipped.kind === "refused") return preflightSkippedNotice(skipped.refusal.message);
|
|
1316
|
+
return preflightUncheckedNotice(skipped.failure.message);
|
|
1317
|
+
}
|
|
1318
|
+
function createProbeSaver(profileName, cached) {
|
|
1319
|
+
let current = cached;
|
|
1320
|
+
let state = "current";
|
|
1321
|
+
return async (fresh) => {
|
|
1322
|
+
if (sameServer(current, fresh)) return state;
|
|
1323
|
+
current = fresh;
|
|
1324
|
+
try {
|
|
1325
|
+
await writeProbeResult(profileName, {
|
|
1326
|
+
user: cached.user,
|
|
1327
|
+
server: fresh
|
|
1328
|
+
});
|
|
1329
|
+
state = "current";
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
warn(`Could not save the server's new probe to profile "${profileName}": ${errorMessage(error)}`);
|
|
1332
|
+
state = "stale";
|
|
1333
|
+
}
|
|
1334
|
+
return state;
|
|
1633
1335
|
};
|
|
1634
1336
|
}
|
|
1635
|
-
async function
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1337
|
+
async function settleRun(run) {
|
|
1338
|
+
let awaited = null;
|
|
1339
|
+
while (awaited !== run.profileSave) {
|
|
1340
|
+
if (run.server !== null) await run.server.client.probesSettled();
|
|
1341
|
+
awaited = run.profileSave;
|
|
1342
|
+
await awaited;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
async function diagnoseFailure(error, run) {
|
|
1346
|
+
if (run.server === null || !isSkewSymptom(error)) return error;
|
|
1347
|
+
const { client, cachedProbe } = run.server;
|
|
1348
|
+
if (cachedProbe === null) {
|
|
1349
|
+
await probeOnTheWayOut(client);
|
|
1350
|
+
return error;
|
|
1351
|
+
}
|
|
1352
|
+
const detail = error instanceof ResponseShapeError ? error.developerDetail : null;
|
|
1353
|
+
if (detail === null || detail.kind !== "zod" || detail.serverTag !== cachedProbe.version.tag) return error;
|
|
1354
|
+
const fresh = await probeOnTheWayOut(client);
|
|
1355
|
+
if (fresh === null) return error;
|
|
1356
|
+
const note = serverChangeNote(cachedProbe, fresh, detail.method, await run.profileSave);
|
|
1639
1357
|
return note === null ? error : new ProfileRefreshedError(error, note);
|
|
1640
1358
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1359
|
+
function isSkewSymptom(error) {
|
|
1360
|
+
if (error instanceof ResponseShapeError) return true;
|
|
1361
|
+
return error instanceof HttpError && error.kind === "route-missing";
|
|
1362
|
+
}
|
|
1363
|
+
async function probeOnTheWayOut(client) {
|
|
1643
1364
|
try {
|
|
1644
|
-
|
|
1365
|
+
return await client.verifiedServer();
|
|
1645
1366
|
} catch (error) {
|
|
1646
|
-
if (error
|
|
1367
|
+
if (isNonInterruptFailure(error)) return null;
|
|
1647
1368
|
throw error;
|
|
1648
1369
|
}
|
|
1649
|
-
const note = serverChangeNote(cached.probe, fresh);
|
|
1650
|
-
if (note === null) return null;
|
|
1651
|
-
await writeProbeResult(cached.profileName, {
|
|
1652
|
-
user: cached.probe.user,
|
|
1653
|
-
server: fresh
|
|
1654
|
-
});
|
|
1655
|
-
return note;
|
|
1656
1370
|
}
|
|
1657
1371
|
function resolveReportFormat(commonArgs, rawArgs, argsDef) {
|
|
1658
1372
|
try {
|
|
@@ -1685,4 +1399,4 @@ function buildConfigFlags(ctx) {
|
|
|
1685
1399
|
return flags;
|
|
1686
1400
|
}
|
|
1687
1401
|
//#endregion
|
|
1688
|
-
export {
|
|
1402
|
+
export { parseOptionalInteger as $, registerClient as A, credentialAuthHeader as B, profileAuthMethod as C, OAUTH_SCOPE as D, revokeOAuthCredential as E, probeBudget as F, ServerSummary as G, oauthCredentialFromTokens as H, probeServer as I, createServerProfile as J, summarizeServer as K, profileFromProperties as L, buildNetworkError as M, isConnectionClosed as N, discoverLoginMetadata as O, PROBE_PATH as P, parseInteger as Q, serverInfoFromProperties as R, ProfileLastFailure as S, USER_AGENT as T, displayUrl as U, credentialSecrets as V, normalizeUrl as W, describeVersion as X, featureGap as Y, SessionProperties as Z, writeProbeFailure as _, readEnvCredentials as a, ProbedUser as b, clearProfile as c, keyringFallbackWarning as d, listProfileRecords as f, writeOAuthProfile as g, resolveRecordCredential as h, explicitProfileName as i, tryDiscoverMetadata as j, exchangeCode as k, consumeKeychainResidualWarning as l, readProfileRecord as m, readCachedServerProfile as n, resolveProfileName as o, readProfileCredential as p, Skew as q, createCredentialRefresher as r, DEFAULT_PROFILE as s, defineMetabaseCommand as t, consumeKeyringDowngradeWarning as u, writeProbeResult as v, OAUTH_CLIENT_NAME as w, ProfileAuthMethod as x, writeProfile as y, assertCredentialHeaderSafe as z };
|