@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,313 +0,0 @@
|
|
|
1
|
-
import { dt as ResponseShapeError, ft as TimeoutError, ht as errorMessage, mt as ValidationError, n as methodRequirements, ut as NetworkError } from "./cli.mjs";
|
|
2
|
-
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 } from "./runtime-C3AL15Dp.mjs";
|
|
3
|
-
import { n as throwIfAborted, r as untilAborted, t as combineAborts } from "./signal-0Yt8JTMn.mjs";
|
|
4
|
-
import { setTimeout } from "node:timers/promises";
|
|
5
|
-
//#region ../client/src/http/response-shape.ts
|
|
6
|
-
async function parseJsonResponse(text, schema, context) {
|
|
7
|
-
try {
|
|
8
|
-
return parseJson(text, schema, { source: context.url });
|
|
9
|
-
} catch (error) {
|
|
10
|
-
if (error instanceof ValidationError) throw ResponseShapeError.fromZodIssues({
|
|
11
|
-
kind: "zod",
|
|
12
|
-
method: context.method,
|
|
13
|
-
url: context.url,
|
|
14
|
-
status: context.status,
|
|
15
|
-
zodIssues: error.developerDetail.zodIssues,
|
|
16
|
-
serverTag: await context.getServerTag(),
|
|
17
|
-
serverSkew: context.serverSkew
|
|
18
|
-
});
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region ../client/src/http/retry.ts
|
|
24
|
-
const BASE_DELAY_MS = 250;
|
|
25
|
-
const MAX_DELAY_MS = 8e3;
|
|
26
|
-
const MS_PER_SECOND = 1e3;
|
|
27
|
-
function backoffDelay({ attempt, retryAfterHeader }) {
|
|
28
|
-
const fromHeader = parseRetryAfter(retryAfterHeader);
|
|
29
|
-
if (fromHeader !== null) return fromHeader;
|
|
30
|
-
return Math.min(MAX_DELAY_MS, BASE_DELAY_MS * 2 ** attempt);
|
|
31
|
-
}
|
|
32
|
-
function parseRetryAfter(header) {
|
|
33
|
-
if (!header) return null;
|
|
34
|
-
const numeric = Number(header);
|
|
35
|
-
if (Number.isFinite(numeric) && numeric >= 0) return Math.round(numeric * MS_PER_SECOND);
|
|
36
|
-
const dateMs = Date.parse(header);
|
|
37
|
-
if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
function sleep(ms, signal) {
|
|
41
|
-
return setTimeout(ms, void 0, { signal });
|
|
42
|
-
}
|
|
43
|
-
async function runWithRetries(attempt, signal) {
|
|
44
|
-
let attemptIndex = 0;
|
|
45
|
-
while (true) {
|
|
46
|
-
const outcome = await attempt(attemptIndex);
|
|
47
|
-
if (outcome.kind === "success") return outcome.response;
|
|
48
|
-
await sleep(outcome.delayMs, signal);
|
|
49
|
-
attemptIndex += 1;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region ../client/src/http/transport.ts
|
|
54
|
-
const UNAUTHORIZED_STATUS = 401;
|
|
55
|
-
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
56
|
-
const OCTET_STREAM_CONTENT_TYPE = "application/octet-stream";
|
|
57
|
-
const TEXT_CONTENT_TYPE_PREFIX = "text/";
|
|
58
|
-
const ERROR_BODY_BYTE_CAP = 64 * 1024;
|
|
59
|
-
const IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
|
|
60
|
-
"GET",
|
|
61
|
-
"HEAD",
|
|
62
|
-
"OPTIONS"
|
|
63
|
-
]);
|
|
64
|
-
function createTransport(config, options) {
|
|
65
|
-
const baseUrl = normalizeUrl(config.url);
|
|
66
|
-
assertCredentialHeaderSafe(config.credential);
|
|
67
|
-
const fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
68
|
-
let settledProfile = options.server ?? null;
|
|
69
|
-
const getServerTag = options.getServerTag ?? (async () => tagOf(settledProfile));
|
|
70
|
-
const serverSkew = () => settledProfile === null ? null : settledProfile.skew;
|
|
71
|
-
const refreshCredential = options.refreshCredential;
|
|
72
|
-
let credential = config.credential;
|
|
73
|
-
const knownSecrets = new Set(credentialSecrets(credential));
|
|
74
|
-
const redactionContext = { knownSecrets };
|
|
75
|
-
let refreshInFlight = null;
|
|
76
|
-
function tryRefreshCredential() {
|
|
77
|
-
const refresh = refreshCredential;
|
|
78
|
-
if (credential.kind !== "oauth" || refresh === void 0) return Promise.resolve(false);
|
|
79
|
-
refreshInFlight ??= refreshOnce(refresh).finally(() => {
|
|
80
|
-
refreshInFlight = null;
|
|
81
|
-
});
|
|
82
|
-
return refreshInFlight;
|
|
83
|
-
}
|
|
84
|
-
async function refreshOnce(refresh) {
|
|
85
|
-
const next = await refresh();
|
|
86
|
-
if (next === null) return false;
|
|
87
|
-
credential = next;
|
|
88
|
-
for (const secret of credentialSecrets(next)) knownSecrets.add(secret);
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
async function attemptOnce(prepared, attempt) {
|
|
92
|
-
const hasRetriesLeft = attempt < prepared.retries;
|
|
93
|
-
const timeoutSignal = AbortSignal.timeout(prepared.timeoutMs);
|
|
94
|
-
const combined = combineAborts(timeoutSignal, prepared.cancelSignal);
|
|
95
|
-
let response;
|
|
96
|
-
try {
|
|
97
|
-
response = await fetchImpl(prepared.url, {
|
|
98
|
-
method: prepared.method,
|
|
99
|
-
headers: prepared.headers,
|
|
100
|
-
body: prepared.body,
|
|
101
|
-
signal: combined
|
|
102
|
-
});
|
|
103
|
-
} catch (error) {
|
|
104
|
-
throwIfAborted(prepared.cancelSignal);
|
|
105
|
-
const isStaleSocketFirstTry = attempt === 0 && isConnectionClosed(error);
|
|
106
|
-
if (prepared.idempotent && (hasRetriesLeft || isStaleSocketFirstTry)) return {
|
|
107
|
-
kind: "retry",
|
|
108
|
-
delayMs: backoffDelay({ attempt })
|
|
109
|
-
};
|
|
110
|
-
if (timeoutSignal.aborted) throw new TimeoutError(`Request timed out after ${prepared.timeoutMs}ms`, {
|
|
111
|
-
kind: "http",
|
|
112
|
-
method: prepared.method,
|
|
113
|
-
url: prepared.url,
|
|
114
|
-
timeoutMs: prepared.timeoutMs
|
|
115
|
-
});
|
|
116
|
-
throw buildNetworkError(error, prepared.method, prepared.url);
|
|
117
|
-
}
|
|
118
|
-
const canRetryStatus = hasRetriesLeft && prepared.idempotent;
|
|
119
|
-
if (!response.ok && isRetryableStatus(response.status) && canRetryStatus) {
|
|
120
|
-
const retryAfter = response.headers.get("Retry-After");
|
|
121
|
-
response.body?.cancel().catch(() => void 0);
|
|
122
|
-
return {
|
|
123
|
-
kind: "retry",
|
|
124
|
-
delayMs: backoffDelay({
|
|
125
|
-
attempt,
|
|
126
|
-
retryAfterHeader: retryAfter
|
|
127
|
-
})
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
if (!response.ok) {
|
|
131
|
-
const rawBody = await readBodyForError(response);
|
|
132
|
-
const serverTag = await getServerTag();
|
|
133
|
-
throw new HttpError({
|
|
134
|
-
status: response.status,
|
|
135
|
-
statusText: response.statusText,
|
|
136
|
-
method: prepared.method,
|
|
137
|
-
url: prepared.url,
|
|
138
|
-
responseHeaders: response.headers,
|
|
139
|
-
rawBody,
|
|
140
|
-
serverTag,
|
|
141
|
-
redactionContext
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
assertContentType(response, prepared);
|
|
145
|
-
return {
|
|
146
|
-
kind: "success",
|
|
147
|
-
response
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
async function executeRaw(prepared) {
|
|
151
|
-
try {
|
|
152
|
-
return await runWithRetries((attempt) => attemptOnce(prepared, attempt), prepared.cancelSignal);
|
|
153
|
-
} catch (error) {
|
|
154
|
-
throwIfAborted(prepared.cancelSignal);
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async function executeWithAuthRefresh(path, opts) {
|
|
159
|
-
const prepared = prepare(path, opts);
|
|
160
|
-
try {
|
|
161
|
-
return {
|
|
162
|
-
response: await executeRaw(prepared),
|
|
163
|
-
prepared
|
|
164
|
-
};
|
|
165
|
-
} catch (error) {
|
|
166
|
-
if (error instanceof HttpError && error.status === UNAUTHORIZED_STATUS) {
|
|
167
|
-
if (await tryRefreshCredential()) {
|
|
168
|
-
const retried = prepare(path, opts);
|
|
169
|
-
return {
|
|
170
|
-
response: await executeRaw(retried),
|
|
171
|
-
prepared: retried
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
throw error;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function prepare(path, opts = {}) {
|
|
179
|
-
const method = opts.method ?? "GET";
|
|
180
|
-
const expectContentType = opts.expectContentType ?? "json";
|
|
181
|
-
const url = buildUrl(baseUrl, path, opts.query);
|
|
182
|
-
const headers = new Headers();
|
|
183
|
-
const auth = credentialAuthHeader(credential);
|
|
184
|
-
headers.set(auth.name, auth.value);
|
|
185
|
-
headers.set("accept", acceptHeader(expectContentType));
|
|
186
|
-
headers.set("user-agent", options.userAgent);
|
|
187
|
-
let body = null;
|
|
188
|
-
if (opts.body !== void 0 && opts.body !== null) if (typeof opts.body === "string" || opts.body instanceof URLSearchParams) body = opts.body;
|
|
189
|
-
else if (opts.body instanceof FormData || opts.body instanceof ReadableStream) body = opts.body;
|
|
190
|
-
else if (opts.body instanceof Uint8Array) {
|
|
191
|
-
body = opts.body;
|
|
192
|
-
headers.set("content-type", OCTET_STREAM_CONTENT_TYPE);
|
|
193
|
-
} else {
|
|
194
|
-
body = JSON.stringify(opts.body);
|
|
195
|
-
headers.set("content-type", JSON_CONTENT_TYPE);
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
url,
|
|
199
|
-
method,
|
|
200
|
-
headers,
|
|
201
|
-
body,
|
|
202
|
-
expectContentType,
|
|
203
|
-
retries: opts.retries ?? 3,
|
|
204
|
-
idempotent: opts.idempotent ?? IDEMPOTENT_METHODS.has(method),
|
|
205
|
-
timeoutMs: opts.timeoutMs ?? 3e4,
|
|
206
|
-
cancelSignal: combineAborts(opts.signal, options.signal)
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
let serverProfile = options.server === void 0 ? null : Promise.resolve(options.server);
|
|
210
|
-
async function server(wait = {}) {
|
|
211
|
-
throwIfAborted(wait.signal);
|
|
212
|
-
if (serverProfile === null) {
|
|
213
|
-
const probe = probeServer(transport).then((info) => {
|
|
214
|
-
settledProfile = createServerProfile(info);
|
|
215
|
-
return settledProfile;
|
|
216
|
-
});
|
|
217
|
-
probe.catch(() => {
|
|
218
|
-
serverProfile = null;
|
|
219
|
-
});
|
|
220
|
-
serverProfile = probe;
|
|
221
|
-
}
|
|
222
|
-
return untilAborted(serverProfile, wait.signal);
|
|
223
|
-
}
|
|
224
|
-
const enforceRequirements = options.enforceRequirements ?? true;
|
|
225
|
-
async function requireFeatures(features, wait = {}) {
|
|
226
|
-
if (!enforceRequirements || features.length === 0) return;
|
|
227
|
-
const failure = checkFeatures(features, await server(wait));
|
|
228
|
-
if (failure !== null) throw new CapabilityError(failure);
|
|
229
|
-
}
|
|
230
|
-
async function requireMethod(key, wait = {}) {
|
|
231
|
-
return requireFeatures(methodRequirements(key), wait);
|
|
232
|
-
}
|
|
233
|
-
const transport = {
|
|
234
|
-
server,
|
|
235
|
-
require: requireMethod,
|
|
236
|
-
requireFeatures,
|
|
237
|
-
async requestRaw(path, opts) {
|
|
238
|
-
return (await executeWithAuthRefresh(path, opts ?? {})).response;
|
|
239
|
-
},
|
|
240
|
-
async requestParsed(schema, path, opts) {
|
|
241
|
-
const { response, prepared } = await executeWithAuthRefresh(path, {
|
|
242
|
-
...opts,
|
|
243
|
-
expectContentType: "json"
|
|
244
|
-
});
|
|
245
|
-
return parseJsonResponse(await response.text(), schema, {
|
|
246
|
-
method: prepared.method,
|
|
247
|
-
url: prepared.url,
|
|
248
|
-
status: response.status,
|
|
249
|
-
getServerTag,
|
|
250
|
-
serverSkew: serverSkew()
|
|
251
|
-
});
|
|
252
|
-
},
|
|
253
|
-
async requestStream(path, opts) {
|
|
254
|
-
const { response, prepared } = await executeWithAuthRefresh(path, {
|
|
255
|
-
...opts,
|
|
256
|
-
expectContentType: opts?.expectContentType ?? "binary"
|
|
257
|
-
});
|
|
258
|
-
if (!response.body) throw new NetworkError("Response had no body to stream", {
|
|
259
|
-
method: prepared.method,
|
|
260
|
-
url: prepared.url,
|
|
261
|
-
cause: "missing body"
|
|
262
|
-
});
|
|
263
|
-
return response.body;
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
return transport;
|
|
267
|
-
}
|
|
268
|
-
function tagOf(profile) {
|
|
269
|
-
return profile === null ? null : profile.version.tag;
|
|
270
|
-
}
|
|
271
|
-
function buildUrl(baseUrl, path, query) {
|
|
272
|
-
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
273
|
-
const target = new URL(baseUrl + normalizedPath);
|
|
274
|
-
if (query) for (const [key, value] of Object.entries(query)) {
|
|
275
|
-
if (value === void 0) continue;
|
|
276
|
-
if (Array.isArray(value)) for (const entry of value) target.searchParams.append(key, String(entry));
|
|
277
|
-
else target.searchParams.append(key, String(value));
|
|
278
|
-
}
|
|
279
|
-
return target.toString();
|
|
280
|
-
}
|
|
281
|
-
function acceptHeader(expected) {
|
|
282
|
-
if (expected === "json") return JSON_CONTENT_TYPE;
|
|
283
|
-
if (expected === "text") return "text/*";
|
|
284
|
-
return "*/*";
|
|
285
|
-
}
|
|
286
|
-
function assertContentType(response, prepared) {
|
|
287
|
-
if (prepared.expectContentType === "binary") return;
|
|
288
|
-
const contentType = response.headers.get("content-type");
|
|
289
|
-
if (contentType === null) throwContentTypeMismatch(response, prepared, prepared.expectContentType);
|
|
290
|
-
if (prepared.expectContentType === "json" && !contentType.includes("application/json")) throwContentTypeMismatch(response, prepared, "json");
|
|
291
|
-
if (prepared.expectContentType === "text" && !contentType.startsWith(TEXT_CONTENT_TYPE_PREFIX)) throwContentTypeMismatch(response, prepared, "text");
|
|
292
|
-
}
|
|
293
|
-
function throwContentTypeMismatch(response, prepared, expected) {
|
|
294
|
-
const actual = response.headers.get("content-type") ?? "no content-type";
|
|
295
|
-
throw new HttpError({
|
|
296
|
-
status: response.status,
|
|
297
|
-
statusText: response.statusText,
|
|
298
|
-
method: prepared.method,
|
|
299
|
-
url: prepared.url,
|
|
300
|
-
responseHeaders: response.headers,
|
|
301
|
-
rawBody: null,
|
|
302
|
-
overrideUserMessage: `Expected ${expected} response but got ${actual}`
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
async function readBodyForError(response) {
|
|
306
|
-
try {
|
|
307
|
-
return Buffer.from(await response.arrayBuffer()).subarray(0, ERROR_BODY_BYTE_CAP).toString("utf8");
|
|
308
|
-
} catch (error) {
|
|
309
|
-
return `[body read failed: ${errorMessage(error)}]`;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
//#endregion
|
|
313
|
-
export { createTransport as n, DEFAULT_TIMEOUT_MS as t };
|
package/dist/update-BQben_Xm.mjs
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { J as outputFlags, U as connectionFlags, Y as profileFlag, p as renderSummary } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-C3AL15Dp.mjs";
|
|
3
|
-
import { t as parseId } from "./parse-id-aMXePsUP.mjs";
|
|
4
|
-
import { t as readBody } from "./body-CT1cQrhp.mjs";
|
|
5
|
-
import { t as bodyInputFlags } from "./body-flags-AqKpN01Y.mjs";
|
|
6
|
-
import { a as TransformTestUpdateInput, t as TransformTest } from "./transform-test-BjjCQ2xm.mjs";
|
|
7
|
-
import { n as transformTestView } from "./transform-test-DHGKeuHa.mjs";
|
|
8
|
-
//#region src/commands/transform-test/update.ts
|
|
9
|
-
var update_default = defineMetabaseCommand({
|
|
10
|
-
meta: {
|
|
11
|
-
name: "update",
|
|
12
|
-
description: "Update a transform test from JSON"
|
|
13
|
-
},
|
|
14
|
-
details: "Only the fields the body carries are patched. `inputs` and `expectations` replace what is stored rather than merging into it. The body is closed at every level: a test read back with `get --full` has to shed `id`, `entity_id`, `creator_id`, `created_at` and `updated_at` before it can be sent.",
|
|
15
|
-
requires: ["transformTest.update"],
|
|
16
|
-
args: {
|
|
17
|
-
...outputFlags,
|
|
18
|
-
...profileFlag,
|
|
19
|
-
...connectionFlags,
|
|
20
|
-
...bodyInputFlags,
|
|
21
|
-
id: {
|
|
22
|
-
type: "positional",
|
|
23
|
-
description: "Transform test id",
|
|
24
|
-
required: true
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
inputSchema: TransformTestUpdateInput,
|
|
28
|
-
outputSchema: TransformTest,
|
|
29
|
-
examples: ["cat patch.json | mb transform-test update 1", "mb transform-test update 1 --file patch.json"],
|
|
30
|
-
async run({ args, ctx, getClient }) {
|
|
31
|
-
const id = parseId(args.id);
|
|
32
|
-
const body = await readBody({
|
|
33
|
-
flag: args.body,
|
|
34
|
-
file: args.file
|
|
35
|
-
}, TransformTestUpdateInput);
|
|
36
|
-
const updated = await (await getClient()).transformTest.update(id, body);
|
|
37
|
-
renderSummary(updated, transformTestView, `Updated transform test ${updated.id}.`, ctx);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
//#endregion
|
|
41
|
-
export { update_default as default };
|
package/dist/upload-BqNErDXE.mjs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { t as defineCommandGroup } from "./group-D4w87fXL.mjs";
|
|
2
|
-
//#region src/commands/upload/index.ts
|
|
3
|
-
var upload_default = defineCommandGroup({
|
|
4
|
-
name: "upload",
|
|
5
|
-
description: "Upload CSV files into Metabase",
|
|
6
|
-
subCommands: {
|
|
7
|
-
csv: () => import("./csv-CX1wws5-.mjs").then((m) => m.default),
|
|
8
|
-
append: () => import("./append-DUFn3_Og.mjs").then((m) => m.default),
|
|
9
|
-
replace: () => import("./replace-COC3ggyx.mjs").then((m) => m.default)
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
//#endregion
|
|
13
|
-
export { upload_default as default };
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: transform-test-plan
|
|
3
|
-
description: Derive a comprehensive test plan for a transform — the fixture cast, the expectations, hand-derived expected rows, and a coverage matrix — from the model's declared design. Covers input partitioning (zero-case, multiplicity, dirty rows), grain / conservation / recomputation / conformance checks, and known-quirk conventions. Load when the user wants tests planned or written for transforms — "write tests for my transforms", "is my model right", "test plan for this pipeline", "add data quality checks" — whether the model is mid-build or already deployed. The `mb transform-test` command and body shapes live in the `transform` skill; this one decides what to test.
|
|
4
|
-
allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
|
|
5
|
-
requires: [transformTests]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Planning transform tests
|
|
9
|
-
|
|
10
|
-
Turn a transform into a fixture cast that proves the logic on small known rows, expectations that state the model's invariants, and a coverage matrix showing what's checked and what's deliberately not. Mechanics — the `inputs`/`expectations` body shape and every `mb transform-test` verb — live in the `transform` skill (`mb skills get transform`); load it before authoring, and never restate it here. The two references this skill routes through, `references/checklist.md` and `references/checks.md`, come with `mb skills get transform-test-plan --full`, or read them from `mb skills path transform-test-plan`.
|
|
11
|
-
|
|
12
|
-
Every check derives from what the model **declares** — detected from its SQL, confirmed with its owner — never from conformance to a modeling doctrine. One plan serves two moments: while the model is **built**, checks pin each design decision; once **deployed**, the same SQL screens production tables for anomalies.
|
|
13
|
-
|
|
14
|
-
## Operating rules
|
|
15
|
-
|
|
16
|
-
- **Detect, then derive.** Classify what the transform is and which conventions it uses (the checklist); derive checks only from that. Star, one-big-table, partial denormalization — all fine; never flag a style.
|
|
17
|
-
- **Judgment calls go through the checklist.** The session's autonomy setting governs which answers you supply yourself and which you bring to the user — it never makes the checklist a formality. Every answer you supply yourself is recorded in the plan as a stated assumption, paired with the named expectation that enforces it — reversing the decision then breaks a test, not a paragraph. And regardless of setting, when genuinely unsure, ask — a wrong-but-confident grain poisons every downstream check.
|
|
18
|
-
- **Expected rows are derived by hand** from the fixture story and business meaning — never captured from the transform's output, which asserts only that the transform equals itself.
|
|
19
|
-
- **Batteries stay off until declared structure switches them on.** No snapshot-density checks without a snapshot, no version-history checks without effective/end/current columns. An empty section beats a speculative one.
|
|
20
|
-
|
|
21
|
-
## The procedure
|
|
22
|
-
|
|
23
|
-
1. **Profile the real inputs**: per table, row count; per column, min/max/distinct-count/null incidence; orphan counts across declared links (`mb field summary`, `mb query`). Profiling feeds domains, bounds, null partitions, and key candidates — and every fixture edge cites the real-data condition that warrants it, with its count ("the warehouse has 67 ship-before-order rows").
|
|
24
|
-
2. **Detect.** Read the transform's SQL (`mb transform get <id> --full --json`) for: grain candidates (`GROUP BY` keys, the joins' driving table), join types (orphan handling), correlated aggregates (stored aggregates), `<entity>_<attr>` naming (copies), effective/end/current columns (version history), `now()`/`current_date` (volatile columns). A transform whose grain you cannot state in one phrase is itself a finding — raise it before writing any test.
|
|
25
|
-
3. **Confirm.** Walk [references/checklist.md](references/checklist.md). Three stages: classify the model, per-table declarations, per-column declarations. Each question carries its detection hint; answer autonomously where the hint resolves, ask where it doesn't. In build-along mode these are design questions — treat an undecided answer as a decision to make together, not a blocker.
|
|
26
|
-
4. **Derive.** Route every output column through [references/checks.md](references/checks.md) — declared property → expectation shape, fixture implication, expected-row convention. Read it in full once per plan; it is the plan's content.
|
|
27
|
-
5. **Design the fixture cast**: one small cast per transform (≈5–10 rows per table), human-named rows ("Alice Premium"), every row a named edge — zero-case entities for every outer join and aggregation, ≥2-member groups for every grouping and join, one dirty row per screenable defect, boundary dates. Document it as a table (row → attributes → purpose) in the plan.
|
|
28
|
-
|
|
29
|
-
Express the cast as literal rows rather than as a query, so the story stays legible in the test itself; a query is worth it only when the rows are mechanical to generate. A cast is written against one warehouse and does not carry to another.
|
|
30
|
-
|
|
31
|
-
6. **Hand-derive the expected rows**, arithmetic recorded in the plan (premium: 3 orders / 350.50 / 3.0). Every fixture row's fate appears in some expected cell. Pin NULL-vs-0-vs-empty for every zero-case row — that cell is the null policy's only enforcement.
|
|
32
|
-
7. **Author the test.** One test per transform, per coherent story: an `equals` pinning the output, declaring every output column, since `equals` compares only the columns it declares, and `empty` expectations stating the invariants that survive a change to the cast.
|
|
33
|
-
|
|
34
|
-
Give each expectation a name that states the invariant, because the name is what a failure leads with ("revenue never negative", not "check 3"), and open each `empty` expectation's SQL with a `--` contract comment: the invariant, and the failure modes it catches ("catches both dropped orders and join fan-out").
|
|
35
|
-
|
|
36
|
-
Where one invariant applies to several transforms, duplicate the SQL. Nothing is shared between tests, so give each copy its own name and comment rather than one that only makes sense next to its twin.
|
|
37
|
-
|
|
38
|
-
8. **Emit the coverage matrix** in the plan: rows = output columns with the table's grain; columns = check classes (grain, conservation, recomputation, conformance, domains, referential integrity, temporal, screens); cells name the covering expectation or expected-row cell, or state `gap: <reason>`. Scan shared-attribute columns across transforms for cross-table agreement obligations. Empty cells are honest; silent gaps are not.
|
|
39
|
-
9. **Prove the tests have teeth.** Once per test: corrupt one expected cell, `run`, confirm `cell-mismatches` names exactly that column; revert. Then perturb one input cell and confirm exactly the declared output cells move. An `empty` expectation that only selects output rows passes against an empty output, so a green test can still be vacuous.
|
|
40
|
-
|
|
41
|
-
## Severity: error, or the tolerated oddity
|
|
42
|
-
|
|
43
|
-
Every expectation is pass or fail, and one failure fails the run. **error** = forbidden, and it becomes an `empty` expectation. There is no warn severity, so **never author an expectation you expect to fire**: a permanently red test trains everyone to ignore the result, and a red run gates everyone else's work.
|
|
44
|
-
|
|
45
|
-
A tolerated-but-surfaced oddity — one the owner lives with, like orphan rows or ship-before-order dates — gets encoded the two ways that hold: **pin it in the `equals` rows** (an orphan passing through with NULLs is a cell in the expected output, so reversing the tolerance breaks the test), and **record it in the plan's known-quirks list** with its real-data count, so the tolerance stays a conscious choice.
|
|
46
|
-
|
|
47
|
-
Under budget pressure cut business-rule checks first, then cross-table structure checks; never single-column screens (domains, ranges, nulls) — cheapest, and the last line.
|
|
48
|
-
|
|
49
|
-
## When a check exposes a live bug
|
|
50
|
-
|
|
51
|
-
Non-negotiable: **never soften the test to green** — expected values state correct behavior; matching them to buggy output documents the bug as intended — and **surface the finding with its blast radius at both scales**, fixture ("1530.24 of 1600.74 fixture dollars survive") and warehouse ("908 of 2,050 orders dropped"). What happens next follows the session's terms, not a fixed protocol: propose and apply the fix now (when the user wants it or the autonomy setting covers it), or — when the fix must wait — hold the correct expectation and record the red in the plan with the minimal fix body. A stored test has no red-by-design state, so a deferred fix must be visible in the plan or the test reads as broken. Either way, once green the test stays as the regression guard.
|
|
52
|
-
|
|
53
|
-
## When the doctrine doesn't apply
|
|
54
|
-
|
|
55
|
-
The vocabulary follows Kimball's dimensional modeling (grain, additivity, conformed attributes, slowly changing dimensions) — precise, widely understood terms. Real models are Kimball-inspired at most; no check may score adherence:
|
|
56
|
-
|
|
57
|
-
- Full calendar date dimensions are rare. Never demand one; test date _semantics_ — ranges, orderings, volatile derivations.
|
|
58
|
-
- Surrogate keys are doctrine, natural-key joins are practice. Test whichever key the model declares; never flag natural-key joins.
|
|
59
|
-
- "No NULL FKs / no NULL attributes" is doctrine routinely dropped. Null policy is three independent declarations — measures, attributes, FKs — each detected and confirmed, never presumed.
|
|
60
|
-
- One-big-table is legitimate: it still has a grain, its copies still need agreement checks, its functional dependencies still hold.
|
|
61
|
-
- A transform-level `ORDER BY` has no testable effect — output tables carry no row order and the `equals` comparison is a multiset. Flag it as probable dead weight (clustering hints aside); never write an ordering expectation.
|
|
62
|
-
|
|
63
|
-
## One transform at a time
|
|
64
|
-
|
|
65
|
-
Each test covers one transform. When the transform under test reads another transform's output, that target table is an input like any other: declare it and fake it. Derive those rows from the base transform's own expected output, so the two tests tell one story, and note the coupling in both plans — changing the base's expected rows means changing this test's input.
|
|
66
|
-
|
|
67
|
-
## Worked example, condensed
|
|
68
|
-
|
|
69
|
-
`orders` + `customers` → _enriched_orders_ (order grain; LEFT JOIN attaches `customer_name`, `tier`).
|
|
70
|
-
|
|
71
|
-
Cast, 7 orders: two tiers; Alice and Carol with 2 orders each (multiplicity); two never shipped (zero-case for the shipping join); order 106 shipped before ordered (real oddity, count cited); order 107's customer_id matches no customer (orphan). Two `rows` inputs, one per source table.
|
|
72
|
-
|
|
73
|
-
Derived, per catalog: grain uniqueness on `order_id`; row and amount conservation from input to output, as scalar subqueries over the target and the seeded input; `tier` domain ⊆ {standard, premium}; orphan = keep-with-NULLs → an expected row pinning the NULL pass-through; ship-before-order tolerated → the plan's known-quirks list with the warehouse count. The whole output, every column, pinned in one `equals`, hand-computed, arithmetic in the plan. The inner-vs-LEFT-join bug this cast catches — unshipped orders silently dropped from revenue — is what the zero-case rows exist for.
|
|
74
|
-
|
|
75
|
-
## Don't
|
|
76
|
-
|
|
77
|
-
- Don't author expectations before loading the `transform` skill — the body shape, the closed create/update contract, and the verb flags live there.
|
|
78
|
-
- Don't capture expected rows from the transform's own output — hand-derive them or they assert nothing.
|
|
79
|
-
- Don't emit checks for structure the model doesn't declare (snapshot density, version history, bridge weights) — an inapplicable battery buries real findings.
|
|
80
|
-
- Don't let a fixture cast go all-clean — no zero-case, no orphan, no dirty row proves the happy path and nothing else; the bugs live in the edges.
|
|
81
|
-
- Don't write an expectation you expect to fail.
|
|
82
|
-
- Don't surface bare check-ids ("per C3…") to the user — name the check in plain words; the ids are for your cross-referencing, not their reading.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Confirmation checklist
|
|
2
|
-
|
|
3
|
-
The judgment calls a plan depends on, in derivation order. Each question carries a **detect** hint — how to answer it from the SQL, the metadata, or profiling. Answer autonomously where the hint resolves cleanly; ask where it doesn't. Every answer you supply yourself goes into the emitted plan as a stated assumption, phrased so the owner can falsify it at a glance ("Assuming `discount` can never be negative — correct?").
|
|
4
|
-
|
|
5
|
-
In build-along mode these are design questions: the owner is deciding, not recalling. An undecided answer is a decision to make together — surface the options and the check each implies (the `checks.md` entry named in parentheses).
|
|
6
|
-
|
|
7
|
-
## Stage 1 — classify the model (per transform)
|
|
8
|
-
|
|
9
|
-
1. **Grain: one row per what?** (G1, G2) Detect: `GROUP BY` keys; otherwise the driving table of the joins. Confirm whenever detection and any written description disagree — that disagreement is itself a finding.
|
|
10
|
-
2. **Fact-table type — and if periodic snapshot, dense or sparse?** (F2) Detect: event-grain with a single event date → transaction; entity×period grain → periodic snapshot (density is the one yes/no that flips its whole invariant set — always confirm); one row per pipeline occurrence with milestone-date columns → accumulating snapshot.
|
|
11
|
-
|
|
12
|
-
## Stage 2 — per-table declarations
|
|
13
|
-
|
|
14
|
-
3. **Conservation ties: output rows/sums tie to which input, with which declared exclusions?** (A2) Detect: `WHERE` clauses and join types name the exclusions (filtered rows, dropped duplicates). Exclusions must be declared, or conservation appears to fail.
|
|
15
|
-
4. **Zero-group policy: does a group with no contributing rows appear (with zeros) or stay absent?** (A5) Detect: driving table of the rollup — grouping the detail can't produce empty groups; joining a dimension first can.
|
|
16
|
-
5. **Orphan handling per join: drop / keep-with-NULLs / default row — and is an orphan tolerated or forbidden?** (C3, I5) Detect: join type. INNER = drop, LEFT = keep-with-NULLs, COALESCE to a sentinel = default row. Tolerated-vs-forbidden is the owner's call — profiling says whether orphans exist today, not whether they're acceptable. Forbidden becomes an `empty` expectation; tolerated is pinned in the expected rows and recorded in the known-quirks list.
|
|
17
|
-
6. **Version history: effective/end/current columns anywhere? If not, confirm overwrite-everywhere.** (T1) Detect: column names. Absence means history is silently rewritten in rollups — state that consequence when confirming, not just the mechanism.
|
|
18
|
-
7. **Does this transform read another transform's output?** (A5) Detect: another transform's target table in this one's SQL. It becomes a declared input like any other, faked from that transform's own expected output — confirm which rows, and record the coupling in both plans.
|
|
19
|
-
|
|
20
|
-
## Stage 3 — per-column declarations
|
|
21
|
-
|
|
22
|
-
8. **Each measure: additive, semi-additive, or non-additive?** (A1) Detect: sums and counts are additive; balances and levels are semi-additive; ratios, rates, and unit prices are non-additive. Confirm the ambiguous ones (a "score"? a "quantity on hand"?).
|
|
23
|
-
9. **Legal bounds per measure?** (Q1) Detect: profiling min/max suggests, business meaning decides — can `discount` be negative? can `quantity` be zero? Derived bounds are free (a sum of non-negatives is non-negative).
|
|
24
|
-
10. **Each derived measure: the exact recomputation rule?** (A3) Detect: the SELECT expression is the rule — but rounding, business-day adjustments, and NULL handling are conventions to confirm, not read.
|
|
25
|
-
11. **Which columns are stored aggregates, over which detail and filter?** (A4) Detect: correlated subqueries / joined-aggregate CTEs in the SQL.
|
|
26
|
-
12. **Which categorical columns have closed domains — enumerate; is NULL a member?** (C2) Detect: profiling distinct values gives today's set; the owner confirms it's closed rather than merely small so far.
|
|
27
|
-
13. **Which columns are denormalized copies, of which owning attribute?** (C1) Detect: `<entity>_<attr>` naming; any column functionally dependent on a non-grain key. Every hit must be classified: copy (C1), stored aggregate (A4), or smuggled coarser-grain fact — a finding.
|
|
28
|
-
14. **Which many-to-one edges hold within one output table?** (C4) Detect: hierarchy-shaped column pairs (product/category, zip/state). Applies where no owning table is in scope; otherwise C1 covers it.
|
|
29
|
-
15. **Which date orderings are business-guaranteed vs. known-violated and tolerated (with real-data counts)?** (T2) Detect: profiling counts the violations that exist; the owner decides tolerated vs. bug.
|
|
30
|
-
16. **Null policy per column — measures, attributes, FKs separately.** (Q2) Detect: the SQL shows what's produced (COALESCE, CASE); the owner confirms intent — "count of nothing": 0 or NULL? empty date: NULL or sentinel?
|
|
31
|
-
17. **Which columns are volatile across runs?** (T3) Detect: `now()` / `current_date` / run-metadata expressions in the SQL. A volatile column is left out of the `equals` columns; its form can still be asserted with an `empty`.
|
|
32
|
-
18. **Per tolerated oddity: does it stay tolerated, and what is its current count?** (Q3) Detect: can't — this is the conscious-choice question, and the plan's known-quirks list is where it survives.
|