@metabase/cli 0.3.2-alpha.fix-transform-test-ee-path.041c793 → 0.3.2
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-73X1DmCM.mjs → add-collection-BjVAdZ1n.mjs} +2 -2
- package/dist/{alert-BB38lWSL.mjs → alert-DCLhfwdv.mjs} +6 -6
- package/dist/{alerts-DxyzqLSU.mjs → alerts-DRin_wt2.mjs} +3 -3
- package/dist/{append-CHme1Enm.mjs → append-DQ9rPJHZ.mjs} +2 -2
- package/dist/{archive-BGiDxu8O.mjs → archive-1YVo-Wsu.mjs} +2 -2
- package/dist/{archive-CP5Hlqjw.mjs → archive-BPCgmLcV.mjs} +2 -2
- package/dist/{archive-DBcxZwLd.mjs → archive-BVRKE9Ev.mjs} +2 -2
- package/dist/{archive-DPL1qOuL.mjs → archive-BzVxRqpL.mjs} +2 -2
- package/dist/{archive-Czo5T0Lp.mjs → archive-COFQAHAL.mjs} +2 -2
- package/dist/{archive-CqKqNdUh.mjs → archive-D3yPvUtz.mjs} +2 -2
- package/dist/{archive-eS-XA74p.mjs → archive-D6xzHaM3.mjs} +2 -2
- package/dist/{archive-Cq3fnc0v2.mjs → archive-HeRygdKz2.mjs} +2 -2
- package/dist/{archive-BMyvyf62.mjs → archive-_c-ISZmi.mjs} +2 -2
- package/dist/{archive-C4Y2B58q.mjs → archive-o5cWV3vZ.mjs} +2 -2
- package/dist/{archive-DKFPJ9j3.mjs → archive-xcgoVPwv.mjs} +2 -2
- package/dist/{auth-6YyB0HNB.mjs → auth-DJn5T6zA.mjs} +4 -4
- package/dist/{body-OjAWKVaU.mjs → body-Cu94pH4P.mjs} +1 -1
- package/dist/{branches-D5YLVFDK.mjs → branches-CUyPxeeW.mjs} +1 -1
- package/dist/{cancel-DeRIq1YJ.mjs → cancel-BNuVls58.mjs} +2 -2
- package/dist/{cancel-task-CqExODVm.mjs → cancel-task-DUmlQQpi.mjs} +1 -1
- package/dist/{card-BMSqofd7.mjs → card-ByOzVxpI.mjs} +7 -7
- package/dist/{cards-B813G9I5.mjs → cards-_gbvw3wp.mjs} +2 -2
- package/dist/cli.mjs +31 -32
- package/dist/{client-cJ7aw0Gt.mjs → client-BnK0evYf.mjs} +162 -2
- package/dist/{collection-BfNg7tEg.mjs → collection-BGbW7u_Q.mjs} +6 -6
- package/dist/{collection-namespace-CVzDgJV0.mjs → collection-namespace-DM90lA8C.mjs} +1 -1
- package/dist/{content-translation-QKWt9l76.mjs → content-translation-CqB3peU9.mjs} +2 -2
- package/dist/{create-CoFg1p6m.mjs → create-B48rmY8v.mjs} +2 -2
- package/dist/{create-DEBgYRlM.mjs → create-B7S5fCkD.mjs} +2 -2
- package/dist/{create-CvpeAcFc.mjs → create-BIUVvIGH.mjs} +2 -2
- package/dist/{create-bvpl6Fn5.mjs → create-BMKuihoI.mjs} +3 -3
- package/dist/{create-CWGsiFvU.mjs → create-BSvTs-EV.mjs} +2 -2
- package/dist/{create-BLiB2xqo.mjs → create-CUHpxANR.mjs} +2 -2
- package/dist/{create-DmKwDQCY2.mjs → create-Cm9Z-rfe2.mjs} +2 -2
- package/dist/{create-BWp6L_dW.mjs → create-CnJKj9Nl.mjs} +2 -2
- package/dist/{create-CMV3qlzJ.mjs → create-CwXUMOMd.mjs} +2 -2
- package/dist/{create-4UnoQvsy.mjs → create-D4Y69cDF.mjs} +2 -2
- package/dist/{create-Bef5eBCA.mjs → create-DMVw9nrZ.mjs} +2 -2
- package/dist/{create-BJad6MR82.mjs → create-DNx9TGHs.mjs} +3 -3
- package/dist/{create-CvIeb1NU.mjs → create-DVo8-IzZ.mjs} +2 -2
- package/dist/{create-D50TxVTk.mjs → create-IFjwHs0G.mjs} +1 -1
- package/dist/{create-branch-BN5iH-GM.mjs → create-branch-Cw-uXows.mjs} +1 -1
- package/dist/{create-DJm0YuLW.mjs → create-va8bByVt.mjs} +2 -2
- package/dist/{csv-BhuX9fwh.mjs → csv-CaKx1oFZ.mjs} +2 -2
- package/dist/{current-task-BMt2NeqV.mjs → current-task-lGh69Z1i.mjs} +1 -1
- package/dist/{dashboard-Ct_ajSYI.mjs → dashboard-Bzjz2v6u.mjs} +9 -9
- package/dist/{db-B_LW2VE-.mjs → db-BRHPjshe.mjs} +6 -6
- package/dist/{delete-CowGO4rh.mjs → delete-BxBadE3q.mjs} +2 -2
- package/dist/{delete-D2bUV6uo.mjs → delete-CQWCfqHf.mjs} +2 -2
- package/dist/{delete-D0f7VatX.mjs → delete-Ci0aDYpf.mjs} +2 -2
- package/dist/{delete-Ur7b11no.mjs → delete-DMETa-37.mjs} +2 -2
- package/dist/{delete-BOcPK_H9.mjs → delete-G6EiGn2Q.mjs} +2 -2
- package/dist/{delete-table-Dd8X573t.mjs → delete-table-N4rZtt1T.mjs} +2 -2
- package/dist/{dependencies-XDVLBwko.mjs → dependencies-edN0P1SS.mjs} +2 -2
- package/dist/{dirty-k-JmGLsS.mjs → dirty-U51bMoCP.mjs} +1 -1
- package/dist/{document-BW9iow8R.mjs → document-DqJ7Cysa.mjs} +5 -5
- package/dist/{download-CQjPIYDO.mjs → download-BJA6k-e6.mjs} +1 -1
- package/dist/{eid-CNTKDgwj.mjs → eid-BtlRU1E0.mjs} +2 -2
- package/dist/{events-BshWlkDp.mjs → events-B5rnOo-L.mjs} +2 -2
- package/dist/{export-Dq6ecU8h.mjs → export-DO2josC0.mjs} +2 -2
- package/dist/{field-Bo2ISMO4.mjs → field-CHZByaXa.mjs} +4 -4
- package/dist/{fields-CVctqn5G.mjs → fields-zQ6O_W_H.mjs} +2 -2
- package/dist/{get-RslzBaXx.mjs → get-93wuhTn2.mjs} +1 -1
- package/dist/{get-8b5Sh50q.mjs → get-BDrmBZ1z.mjs} +2 -2
- package/dist/{get-BD81MHl_.mjs → get-BLcS4il2.mjs} +2 -2
- package/dist/{get-CrpwxWOV.mjs → get-BLjcCXp8.mjs} +2 -2
- package/dist/{get-Dr-U321T2.mjs → get-BSoMWp4t2.mjs} +2 -2
- package/dist/{get-Dw7jAno3.mjs → get-CG6G-mzV.mjs} +2 -2
- package/dist/{get-PWhOdz1z.mjs → get-CTp5l7aU.mjs} +1 -1
- package/dist/{get-CTPvdcud.mjs → get-CeSQptdl.mjs} +2 -2
- package/dist/{get-BvgEF--n.mjs → get-CekXFP3x.mjs} +2 -2
- package/dist/{get-Bl3OmlBP.mjs → get-Cf6a4fFN.mjs} +2 -2
- package/dist/{get-7xTeNGAo.mjs → get-CwiJWeH4.mjs} +2 -2
- package/dist/{get-CO6X4nZH.mjs → get-DC_huYD8.mjs} +3 -3
- package/dist/{get-Df6cGHCM.mjs → get-DXwlZjw0.mjs} +2 -2
- package/dist/{get-D4oGhZWX.mjs → get-Dg-S07ri.mjs} +2 -2
- package/dist/{get-DfMVlz64.mjs → get-DhpMuTSt.mjs} +1 -1
- package/dist/{get-C5sWciaE.mjs → get-EFsmL4le.mjs} +2 -2
- package/dist/{get-wjIgUlNl.mjs → get-is8x5f2n.mjs} +2 -2
- package/dist/{get-run-CZdDqfUj.mjs → get-run-DwY4sFGy.mjs} +2 -2
- package/dist/{get-B4RgW-VT.mjs → get-xPv7e5Ez.mjs} +2 -2
- package/dist/{get-BvSA_mmf.mjs → get-yHIEezeG.mjs} +2 -2
- package/dist/git-sync-NhfLSZA6.mjs +28 -0
- package/dist/{has-remote-changes-i-3MVxat.mjs → has-remote-changes-DE2_14FK.mjs} +1 -1
- package/dist/{import-DWEKejya.mjs → import-Cs7wk058.mjs} +2 -2
- package/dist/{is-dirty-C5ipqd4v.mjs → is-dirty-XqDfqXGi.mjs} +1 -1
- package/dist/{items-hKJ2ZDwy.mjs → items-BloAjPwA.mjs} +1 -1
- package/dist/{library-B7_04UVK.mjs → library-Dgq_5BFh.mjs} +4 -4
- package/dist/{list-Bs7_Rysg.mjs → list-3ErmGdY0.mjs} +1 -1
- package/dist/{list-DfRqNH1N.mjs → list-BZnf3RmA.mjs} +1 -1
- package/dist/{list-oX2SMzxZ.mjs → list-BfLo1xI8.mjs} +1 -1
- package/dist/{list-CgH-H-O6.mjs → list-Bzm5mXRo.mjs} +1 -1
- package/dist/{list-DKcC4cm0.mjs → list-CUJ1wem9.mjs} +1 -1
- package/dist/{list-Cen-7uTo.mjs → list-CUXlZiS1.mjs} +1 -1
- package/dist/{list-CjNXskB4.mjs → list-CZCaqPoo.mjs} +1 -1
- package/dist/{list-DI820W6w.mjs → list-CghNKfYJ.mjs} +1 -1
- package/dist/{list-1vdClKSE.mjs → list-D04uiS3F.mjs} +1 -1
- package/dist/{list-DjwnsyXM.mjs → list-D9d5ocYi.mjs} +3 -3
- package/dist/{list-DKZnQ4Ts.mjs → list-DboUvg-Y.mjs} +1 -1
- package/dist/{list-6myofqMv.mjs → list-DgteFn01.mjs} +2 -2
- package/dist/{list-CmFh1GQ_.mjs → list-DuJezLm_.mjs} +1 -1
- package/dist/{list-CLZU_EOf.mjs → list-VzrtA9lt.mjs} +1 -1
- package/dist/{list-VNC-_E59.mjs → list-f8Csdjyc.mjs} +1 -1
- package/dist/{list-eKDT1XXk.mjs → list-sdCIS2Df.mjs} +3 -3
- package/dist/{list-B-9QOX9Y.mjs → list-vsXIMssK.mjs} +1 -1
- package/dist/{list-D6tTvYUP.mjs → list-yV6CyPzn.mjs} +1 -1
- package/dist/{login-DumZaWXK.mjs → login-Vw51Gts5.mjs} +3 -3
- package/dist/{logout-BsXPRc-3.mjs → logout-BDIqoVhv.mjs} +1 -1
- package/dist/{measure-BFxkbAoa.mjs → measure-LY9Tp9QZ.mjs} +5 -5
- package/dist/{parameter-values-CoF9Hx1p.mjs → parameter-values-DWjmO7Ai.mjs} +2 -2
- package/dist/{parse-id-DmFJgpY6.mjs → parse-id-whJX4DAb.mjs} +1 -1
- package/dist/{path-BQ4lRDyN.mjs → path-BUUAGYO5.mjs} +2 -2
- package/dist/{preflight-BTQe4swo.mjs → preflight-DcULqq8E.mjs} +1 -1
- package/dist/{publish-CFB2Cc5A.mjs → publish-qVFmJQ1E.mjs} +2 -2
- package/dist/{query-CV2KCS5O.mjs → query-BPtIy79s.mjs} +2 -2
- package/dist/{query-BJbUnAHf.mjs → query-Cq1lmqL5.mjs} +2 -2
- package/dist/{remove-collection-D3yvKH3e.mjs → remove-collection-DBqh2Lqm.mjs} +2 -2
- package/dist/{render-BJRCs7rA.mjs → render-Gx1hR7IF.mjs} +1 -1
- package/dist/{replace-uj4WTqx_.mjs → replace-CujInVY9.mjs} +2 -2
- package/dist/{rescan-values-CzxQU318.mjs → rescan-values-HypqBCSK.mjs} +2 -2
- package/dist/{run-B2f_omHu.mjs → run-DEkQSOQa.mjs} +2 -2
- package/dist/{run-yX2dtmE5.mjs → run-b3jyF29q.mjs} +3 -3
- package/dist/{runs-DzUO45wU.mjs → runs-GHqHLGy4.mjs} +2 -2
- package/dist/{runtime-arKqJqIT.mjs → runtime-nCPku2nN.mjs} +1 -1
- package/dist/{schema-tables-DZCNzuQ6.mjs → schema-tables-B5L05Y1L.mjs} +2 -2
- package/dist/{schemas-2ejqaVsG.mjs → schemas-Clx26p_4.mjs} +2 -2
- package/dist/{search-DcihauDZ.mjs → search-DxiuY5EV.mjs} +2 -2
- package/dist/{segment-BQT2poPG.mjs → segment-DiRJcbam.mjs} +5 -5
- package/dist/{selectors-BzestDld.mjs → selectors-rEFuyXPZ.mjs} +2 -2
- package/dist/{send-DMxoLFo7.mjs → send-DIHkDNBN.mjs} +2 -2
- package/dist/{set-CDmiD0vv.mjs → set-D77qUZML.mjs} +2 -2
- package/dist/{set-active-RrvWR9NY.mjs → set-active-DCdFgD0O.mjs} +1 -1
- package/dist/{setting-BiBLCcxz.mjs → setting-DR9bj232.mjs} +3 -3
- package/dist/{setup-DYsTzkWO.mjs → setup-DGa2LLEp.mjs} +2 -2
- package/dist/{skill-list-D9_1Pmt7.mjs → skill-list-DAvGGHzS.mjs} +1 -1
- package/dist/{skills-C3bxxC6a.mjs → skills-CCn7cyMP.mjs} +3 -3
- package/dist/{skills-BPHXUfeL.mjs → skills-CqtNuSXM.mjs} +1 -1
- package/dist/{snippet-BtfxE60H.mjs → snippet-g9JTDxqu.mjs} +5 -5
- package/dist/{stash-DdheS0Ad.mjs → stash-BTtsV0AG.mjs} +2 -2
- package/dist/{status-CXouQJ31.mjs → status-CW7Dt-nV.mjs} +1 -1
- package/dist/{status-BuIzXRX1.mjs → status-XgSS3StV.mjs} +2 -2
- package/dist/{subscription-CJ8Igs1U.mjs → subscription-CofRU47d.mjs} +5 -5
- package/dist/{subscriptions-D0NpGvCQ.mjs → subscriptions-DCuuPF6U.mjs} +3 -3
- package/dist/{summary-D04S8gGj.mjs → summary-uGlgKE3C.mjs} +2 -2
- package/dist/{sync-schema-DrA5zkdl.mjs → sync-schema-Cu9rD3eH.mjs} +3 -3
- package/dist/{table-Dntbz7Q2.mjs → table-Di-EY7pg.mjs} +4 -4
- package/dist/{timeline-8jwsldo3.mjs → timeline-D7EsWZm6.mjs} +7 -7
- package/dist/{timeline-event-BbB1xEdI.mjs → timeline-event-D-h0A_oh.mjs} +5 -5
- package/dist/transform-8XK1LIgC.mjs +28 -0
- package/dist/transform-job-CTizQkWy.mjs +22 -0
- package/dist/{transform-tag-PjryheLF.mjs → transform-tag-BLp_p9J-.mjs} +4 -4
- package/dist/{transforms-CijX3VE7.mjs → transforms-n2IwEcbU.mjs} +2 -2
- package/dist/{tree-Cmb3O6rH.mjs → tree-cqxiDh2b.mjs} +1 -1
- package/dist/{unpublish-DkP_AcK5.mjs → unpublish-DVQCAa3g.mjs} +2 -2
- package/dist/{update-BFyRBc-H.mjs → update-B7CikkI0.mjs} +4 -4
- package/dist/{update-CtLbFCd_.mjs → update-C05J2nZ2.mjs} +3 -3
- package/dist/{update-D8htjzNJ.mjs → update-CAsqNhDC.mjs} +3 -3
- package/dist/{update-D9kOTr0n.mjs → update-CKDRuduL.mjs} +3 -3
- package/dist/{update-COcx61Ur.mjs → update-ChpOukqq.mjs} +3 -3
- package/dist/{update-DPTio6i1.mjs → update-CnkPYL2i.mjs} +3 -3
- package/dist/{update-KSHnb6vB.mjs → update-D4ggtuG4.mjs} +4 -4
- package/dist/{update-DlWB9s0v.mjs → update-D9H6Lh5U.mjs} +3 -3
- package/dist/{update-8UmD1prT.mjs → update-DFdBeJwc.mjs} +3 -3
- package/dist/{update-FCP5Lop2.mjs → update-DKO9HF1f.mjs} +3 -3
- package/dist/{update-BrXGg3QO.mjs → update-DScUzKLI.mjs} +3 -3
- package/dist/{update-DubrpPbz.mjs → update-DffrdV4b.mjs} +3 -3
- package/dist/{update-C91m9YAR.mjs → update-NGq0yXZk.mjs} +3 -3
- package/dist/{update-dashcard-BlibHa5o.mjs → update-dashcard-DvPqLJ3N.mjs} +3 -3
- package/dist/{update-D6Zzvc7F.mjs → update-oQeQyqKO.mjs} +3 -3
- package/dist/{update-Dz47cKBk.mjs → update-rFRPLlb6.mjs} +3 -3
- package/dist/{upgrade-EwL6wPSY.mjs → upgrade-BRgw0fvn.mjs} +1 -1
- package/dist/{upload-D0KaTqUE.mjs → upload-BrfbcbBW.mjs} +1 -1
- package/dist/{upload-BZshRJIM.mjs → upload-VXBFKzLT.mjs} +3 -3
- package/dist/{uuid-DjKLDIVE.mjs → uuid-B4eij1d7.mjs} +1 -1
- package/dist/{values-Dc9612_L.mjs → values-xgOftPq5.mjs} +2 -2
- package/dist/{verify-DVN1eqXZ.mjs → verify-DTOA_wVM.mjs} +2 -2
- package/dist/{wait-C-ovOTAZ.mjs → wait-BjeFgR13.mjs} +2 -2
- package/dist/{wait-flags-BQNmuvIj.mjs → wait-flags-BCeCnaz3.mjs} +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +8 -14
- package/skill-data/transform/SKILL.md +1 -63
- package/dist/create-uanpKsPo.mjs +0 -34
- package/dist/delete-DZ_ICQug.mjs +0 -44
- package/dist/get-BtTetWzm.mjs +0 -32
- package/dist/git-sync-BmoRk0UV.mjs +0 -28
- package/dist/list-CHuhMXet.mjs +0 -35
- package/dist/run-DlO1J1Sx.mjs +0 -50
- package/dist/transform-job-B-1YAbvy.mjs +0 -22
- package/dist/transform-m6s4kkWU.mjs +0 -28
- package/dist/transform-test-BjjCQ2xm.mjs +0 -169
- package/dist/transform-test-DSTkKKNC.mjs +0 -16
- package/dist/transform-test-gzDcbypy.mjs +0 -25
- package/dist/update-Ci8YL4_2.mjs +0 -41
- package/skill-data/transform-test-plan/SKILL.md +0 -171
- package/skill-data/transform-test-plan/references/checklist.md +0 -81
- package/skill-data/transform-test-plan/references/checks.md +0 -260
package/skill-data/core/SKILL.md
CHANGED
|
@@ -6,17 +6,17 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
|
|
|
6
6
|
|
|
7
7
|
# metabase-cli (core)
|
|
8
8
|
|
|
9
|
-
`mb` drives a Metabase instance over its REST API:
|
|
9
|
+
The official Metabase CLI (`mb`) drives a Metabase instance over its REST API: auth, list/get/create/update/delete on every resource, query and transform execution, content search, git-sync (representations ↔ instance), and entity-id translation.
|
|
10
10
|
|
|
11
11
|
Top-level command groups (run `mb <group> --help` to discover verbs):
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
auth | db | table | field | upload | content-translation | query | card | dashboard | snippet | segment | measure | collection | library
|
|
15
|
-
document | timeline | timeline-event | transform | transform-job | transform-tag |
|
|
15
|
+
document | timeline | timeline-event | transform | transform-job | transform-tag | alert | subscription | setting
|
|
16
16
|
search | git-sync | setup | eid | uuid | upgrade | skills
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The conventions below — auth, flags, output, body input — hold across **every** group. When a card needs a query, prefer MBQL over native SQL (portable, pre-flight-validated — load `mbql`); fall back to native SQL when MBQL can't express it.
|
|
19
|
+
The conventions below — auth, flags, output, body input — hold across **every** group. Per-command flags and examples live in each command's `--help`; add `--json` for the machine-readable form with the output JSON Schema. A few flows have their own skills (see "Specialized skills"). When a card needs a query, prefer MBQL over native SQL (portable, pre-flight-validated — load `mbql`); fall back to native SQL when MBQL can't express it.
|
|
20
20
|
|
|
21
21
|
## Auth & profiles
|
|
22
22
|
|
|
@@ -28,7 +28,7 @@ mb auth status --json # → {profile, present, url} for the d
|
|
|
28
28
|
mb auth status --profile <name> --json # health probe for one profile
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
`auth list` is the primary enumeration path — one call returns every profile with sanitized URL, an `authenticated` flag, and a probe `status` (`ok` / `auth-failed` / `network-error` / `server-error` / `not-probed`).
|
|
31
|
+
`auth list` is the primary enumeration path — one call returns every profile with sanitized URL, an `authenticated` flag, and a probe `status` (`ok` / `auth-failed` / `network-error` / `server-error` / `not-probed`). Use it before asking which profile to pick.
|
|
32
32
|
|
|
33
33
|
- One profile and intent doesn't disambiguate → use it.
|
|
34
34
|
- Several → ask via `AskUserQuestion`, presenting the names from `auth list`.
|
|
@@ -69,10 +69,10 @@ Every list verb takes `--limit <n>` (items this call returns) and `--offset <n>`
|
|
|
69
69
|
|
|
70
70
|
- **`has_more` decides whether to keep going — never compare counts.** `total` is the server's count on endpoints that report one and `null` on those that don't, so arithmetic over it is not a termination condition.
|
|
71
71
|
- **To continue, pass `next_offset` back as `--offset`.** When `has_more` is true `next_offset` is past the offset you sent, so the loop advances; when false the walk is over and `next_offset` is `null`.
|
|
72
|
-
- **`truncated` means the byte cap cut the output, not that the data ran out.** `has_more`/`next_offset` are recomputed to the cut point, so a capped list resumes like any window. Its `bytes` is what the untruncated answer would have measured, so it sizes the work left rather than the reply you hold. Narrow rows with `--fields` rather than raising `--max-bytes` — the cap counts only what you asked for, so `--fields` buys rows directly. A capped list always returns at least one row; when not even one fits it exits 2 with "the smallest response this list can produce is N bytes, over the M-byte --max-bytes cap; …".
|
|
72
|
+
- **`truncated` means the byte cap cut the output, not that the data ran out.** `has_more`/`next_offset` are recomputed to the cut point, so a capped list resumes like any window. Its `bytes` is what the untruncated answer would have measured, so it sizes the work left rather than the reply you hold. Narrow rows with `--fields` rather than raising `--max-bytes` — a bigger cap spends context on fields you didn't ask for, and the cap counts only what you asked for, so `--fields` buys rows directly. A capped list always returns at least one row; when not even one fits it exits 2 with "the smallest response this list can produce is N bytes, over the M-byte --max-bytes cap; …".
|
|
73
73
|
- `limit` is echoed only when you passed `--limit` — except `mb search`, which defaults to `--limit 20` (an unbounded search is expensive server-side) and so always reports one. On nouns the server doesn't page, one large `--limit` with narrow `--fields` is a single request; many small `--offset` hops are one request each.
|
|
74
74
|
|
|
75
|
-
The whole walk:
|
|
75
|
+
The whole walk, literally:
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
offset=0
|
|
@@ -104,7 +104,7 @@ mb <noun> create --file ./.scratch/body.json --profile <n> --json
|
|
|
104
104
|
|
|
105
105
|
Single-quoted `'EOF'` stops the shell interpolating `$vars` inside the JSON.
|
|
106
106
|
|
|
107
|
-
Write working files to **`./.scratch`** in the current directory (`mkdir -p ./.scratch` first), never `/tmp` — they persist across the session and the user can review them.
|
|
107
|
+
Write working files to **`./.scratch`** in the current directory (`mkdir -p ./.scratch` first), never `/tmp` — better permissions, they persist across the session, and the user can review them.
|
|
108
108
|
|
|
109
109
|
## Discovering commands and schemas
|
|
110
110
|
|
|
@@ -123,7 +123,7 @@ mb transform --help --json | jq -r '.commands[].command' # verbs under "transfo
|
|
|
123
123
|
|
|
124
124
|
## Resource quirks worth memorizing
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
Routine verb shapes (list / get / create / update), every flag, and output schemas live in each command's `--help` (add `--json` for output schemas). Below is only what help does _not_ tell you: footguns and non-obvious behaviors.
|
|
127
127
|
|
|
128
128
|
- **db traversal: the hydration ladder.** Start with `database get <db-id> --include tables` — the compact table map (id, name, schema, description per table), one call that fits most databases. Pick the relevant tables, then `table fields <table-id>` per table (bounded: fields are per-table). `--include tables.fields` is the full rollup — small databases only. Hundreds of tables? Traverse by schema (`database schemas <db-id>` → `database schema-tables <db-id> <schema>`) or look tables up by name (`search <term> --models table --db-id <db-id> --limit 10`). `sync-schema` / `rescan-values` queue async work and return `{status:"ok"}` immediately; `sync-schema --wait` blocks until `initial_sync_status: complete`.
|
|
129
129
|
- **table fields.** `table get` never returns fields on its own — pass `--include fields` (compact; the underlying query_metadata response also carries FK targets and dimensions, visible under `--full`) or use `table fields <id>` (list envelope). `table update` patches table-level metadata only; physical columns aren't editable.
|
|
@@ -144,9 +144,6 @@ Only what `--help` does _not_ tell you: footguns and non-obvious behaviors.
|
|
|
144
144
|
- **search vs. list.** For plain enumeration of cards/dashboards/collections use the dedicated `… list` verbs; reach for `search --models <kind>` only for ranking against a query string or a cross-resource lookup.
|
|
145
145
|
<!-- requires: transforms -->
|
|
146
146
|
- **transform.** Iterate with `transform update <id>`, never `delete` + `create` (keeps the row, `entity_id`, materialized table, and YAML filename — avoids `_2` suffixes and noisy git history). `transform run` needs `--wait` (or `--sync`, which also waits for the output table to register and returns `target_table_id`) or you get only `{run_id, final:null}`. (→ `transform`.)
|
|
147
|
-
<!-- /requires -->
|
|
148
|
-
<!-- requires: transformTests -->
|
|
149
|
-
- **transform-test.** `transform-test run <id>` checks a transform against fixtures in temp tables — no real table is read — and exits non-zero unless it passes. (→ `transform`.)
|
|
150
147
|
<!-- /requires -->
|
|
151
148
|
- **setup is one-shot.** `mb setup` walks `/api/setup` for a **fresh** instance only — errors against an already-configured one. Mostly for bootstrapping local / e2e instances.
|
|
152
149
|
- **eid** translates a string entity id → numeric id: `mb eid --model <model> <eid1,eid2> --json`. Entity ids are NanoIDs that can start with `-`, which the positional form misreads as a flag (shell quotes don't help) — for those, use `--body '{"entity_ids":{"card":["-…"]}}'` (the id is a JSON string value, immune to flag parsing).
|
|
@@ -167,9 +164,6 @@ This file is enough for any single-command task. For anything deeper, load the r
|
|
|
167
164
|
- **`notification`** — scheduled delivery: question alerts (`mb alert`) and dashboard subscriptions (`mb subscription`). Choosing between them, the two schedule/recipient contracts, channel prerequisites, testing a send.
|
|
168
165
|
<!-- requires: transforms -->
|
|
169
166
|
- **`transform`** — transform body JSON, create + run-with-wait, run inspection, tags, jobs.
|
|
170
|
-
<!-- /requires -->
|
|
171
|
-
<!-- requires: transformTests -->
|
|
172
|
-
- **`transform-test-plan`** — deciding _what_ to test in a transform: the fixture cast, the expectations, the coverage matrix. (`transform` has the `mb transform-test` shapes.)
|
|
173
167
|
<!-- /requires -->
|
|
174
168
|
- **`document`** — Metabase documents (TipTap body, embedding cards).
|
|
175
169
|
<!-- requires: remoteSync -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: transform
|
|
3
|
-
description: Author and run Metabase transforms via `mb` — body shape (native SQL or structured MBQL), create + run-with-wait, run inspection, dependencies, cancel, the `update`-vs-recreate iteration rule, the writable-keys-only PATCH contract,
|
|
3
|
+
description: Author and run Metabase transforms via `mb` — body shape (native SQL or structured MBQL), create + run-with-wait, run inspection, dependencies, cancel, the `update`-vs-recreate iteration rule, the writable-keys-only PATCH contract, plus transform tags and tag-driven transform-job schedules. Load when the user touches transforms — "create a transform", "run a transform", "fix a failing transform", "list transform runs", "cancel a running transform", "manage transform tags", "run a transform job", or anything `mb transform …` / `mb transform-job …` / `mb transform-tag …`.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
|
|
5
5
|
requires: [transforms]
|
|
6
6
|
---
|
|
@@ -173,68 +173,6 @@ mb transform run "$ID" --wait --profile <n> --json # → succeeded
|
|
|
173
173
|
|
|
174
174
|
If you really must `create + delete` instead, do the `delete` **before** the first `git-sync export` so the failed entity never lands in git history — an export of a soft-failed state is noise that needs a follow-up cleanup commit. See `git-sync`, "Read state before mutating", for the ordering rule.
|
|
175
175
|
|
|
176
|
-
<!-- requires: transformTests -->
|
|
177
|
-
|
|
178
|
-
## Transform tests
|
|
179
|
-
|
|
180
|
-
A transform test replaces every table the transform reads with a fixture, runs it into a temp table, and checks that output. No real table is read or written.
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
mb transform-test list --transform <id> --profile <n> --json # --transform is optional
|
|
184
|
-
mb transform-test get <id> --full --profile <n> --json # --full for inputs/expectations
|
|
185
|
-
mb transform-test create --file ./.scratch/test.json --profile <n> --json
|
|
186
|
-
mb transform-test update <id> --file ./.scratch/patch.json --profile <n> --json
|
|
187
|
-
mb transform-test delete <id> --yes --profile <n>
|
|
188
|
-
mb transform-test run <id> --profile <n> --json # exits non-zero unless it passes
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**`inputs`** — one per table the transform reads, each naming a `table` plus either `format: "sql"` with `sql`, or `format: "rows"` with `columns` (each a `name` and a `cast_type`) and `rows`.
|
|
192
|
-
|
|
193
|
-
**`cast_type` is a `CAST` target, not a column type**, and the two vocabularies differ per warehouse: MySQL casts to `SIGNED` and reports `BIGINT`; ClickHouse takes `Nullable(Int32)` for a column that is `Int64`. So a body is warehouse-specific — don't copy a `database_type` out of a run result into a `cast_type`, and don't expect one body to run everywhere.
|
|
194
|
-
|
|
195
|
-
**`expectations`** — `type: "empty"` with the `sql` that must return no rows, or `type: "equals"`, which needs the same `format` split as an input (`"rows"` with `columns`/`rows`, or `"sql"` with a query). An `equals` without a `format` is refused.
|
|
196
|
-
|
|
197
|
-
**Expectation SQL may only name the transform's target table and its declared input tables.** Those are rewritten to the run's temp tables; any other table is refused with `transform-test.unremapped-reference` (400), at `create`/`update` as well as `run`. Expectation names are unique within a test, and every `rows` row carries exactly its declared columns — both refused with the offending name.
|
|
198
|
-
|
|
199
|
-
```json
|
|
200
|
-
{
|
|
201
|
-
"transform_id": 1,
|
|
202
|
-
"name": "adults only",
|
|
203
|
-
"inputs": [
|
|
204
|
-
{
|
|
205
|
-
"table": { "schema": "public", "name": "people" },
|
|
206
|
-
"format": "rows",
|
|
207
|
-
"columns": [
|
|
208
|
-
{ "name": "id", "cast_type": "INTEGER" },
|
|
209
|
-
{ "name": "age", "cast_type": "INTEGER" }
|
|
210
|
-
],
|
|
211
|
-
"rows": [
|
|
212
|
-
{ "id": 1, "age": 30 },
|
|
213
|
-
{ "id": 2, "age": 12 }
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
],
|
|
217
|
-
"expectations": [
|
|
218
|
-
{
|
|
219
|
-
"type": "equals",
|
|
220
|
-
"name": "exactly one row, id 1",
|
|
221
|
-
"format": "rows",
|
|
222
|
-
"columns": [{ "name": "id", "cast_type": "INTEGER" }],
|
|
223
|
-
"rows": [{ "id": 1 }]
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
"type": "empty",
|
|
227
|
-
"name": "no null ids",
|
|
228
|
-
"sql": "SELECT * FROM public.adults WHERE id IS NULL"
|
|
229
|
-
}
|
|
230
|
-
]
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Create and update bodies are closed — strip `id`, `entity_id`, `creator_id`, `created_at` and `updated_at` from a `get --full` body before sending it back.
|
|
235
|
-
|
|
236
|
-
<!-- /requires -->
|
|
237
|
-
|
|
238
176
|
## Drop the materialized table (keep the transform)
|
|
239
177
|
|
|
240
178
|
```bash
|
package/dist/create-uanpKsPo.mjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { H as outputFlags, U as profileFlag, p as renderSummary, z as connectionFlags } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-arKqJqIT.mjs";
|
|
3
|
-
import { t as readBody } from "./body-OjAWKVaU.mjs";
|
|
4
|
-
import { t as bodyInputFlags } from "./body-flags-AqKpN01Y.mjs";
|
|
5
|
-
import { r as TransformTestCreateInput, t as TransformTest } from "./transform-test-BjjCQ2xm.mjs";
|
|
6
|
-
import { t as transformTestView } from "./transform-test-gzDcbypy.mjs";
|
|
7
|
-
//#region src/commands/transform-test/create.ts
|
|
8
|
-
var create_default = defineMetabaseCommand({
|
|
9
|
-
meta: {
|
|
10
|
-
name: "create",
|
|
11
|
-
description: "Create a transform test from JSON"
|
|
12
|
-
},
|
|
13
|
-
details: "The JSON body needs a `transform_id`, a `name`, the `inputs` standing in for every table the transform reads, and the `expectations` checked against its output. An input names its `table` and carries either `format: \"sql\"` with a `sql` query or `format: \"rows\"` with `columns` and `rows`. An expectation is either `type: \"empty\"` with the `sql` that must return nothing, or `type: \"equals\"`, which takes the same `format` split as an input: `format: \"rows\"` with the `columns` and `rows` the output must hold, or `format: \"sql\"` with a query returning them. The body is closed: 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.",
|
|
14
|
-
requires: ["transformTest.create"],
|
|
15
|
-
args: {
|
|
16
|
-
...outputFlags,
|
|
17
|
-
...profileFlag,
|
|
18
|
-
...connectionFlags,
|
|
19
|
-
...bodyInputFlags
|
|
20
|
-
},
|
|
21
|
-
inputSchema: TransformTestCreateInput,
|
|
22
|
-
outputSchema: TransformTest,
|
|
23
|
-
examples: ["cat transform-test.json | mb transform-test create", "mb transform-test create --file transform-test.json"],
|
|
24
|
-
async run({ args, ctx, getClient }) {
|
|
25
|
-
const body = await readBody({
|
|
26
|
-
flag: args.body,
|
|
27
|
-
file: args.file
|
|
28
|
-
}, TransformTestCreateInput);
|
|
29
|
-
const created = await (await getClient()).transformTest.create(body);
|
|
30
|
-
renderSummary(created, transformTestView, `Created transform test ${created.id} "${created.name}".`, ctx);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
//#endregion
|
|
34
|
-
export { create_default as default };
|
package/dist/delete-DZ_ICQug.mjs
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { H as outputFlags, U as profileFlag, z as connectionFlags } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-arKqJqIT.mjs";
|
|
3
|
-
import { t as parseId } from "./parse-id-DmFJgpY6.mjs";
|
|
4
|
-
import { n as confirmAndDelete, t as DeleteResult } from "./delete-runtime-BKEzJn22.mjs";
|
|
5
|
-
//#region src/commands/transform-test/delete.ts
|
|
6
|
-
var delete_default = defineMetabaseCommand({
|
|
7
|
-
meta: {
|
|
8
|
-
name: "delete",
|
|
9
|
-
description: "Delete a transform test by id"
|
|
10
|
-
},
|
|
11
|
-
requires: ["transformTest.delete"],
|
|
12
|
-
args: {
|
|
13
|
-
...outputFlags,
|
|
14
|
-
...profileFlag,
|
|
15
|
-
...connectionFlags,
|
|
16
|
-
yes: {
|
|
17
|
-
type: "boolean",
|
|
18
|
-
description: "Skip confirmation",
|
|
19
|
-
default: false
|
|
20
|
-
},
|
|
21
|
-
id: {
|
|
22
|
-
type: "positional",
|
|
23
|
-
description: "Transform test id",
|
|
24
|
-
required: true
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
outputSchema: DeleteResult,
|
|
28
|
-
examples: ["mb transform-test delete 1 --yes", "mb transform-test delete 1"],
|
|
29
|
-
async run({ args, ctx, getClient }) {
|
|
30
|
-
const id = parseId(args.id);
|
|
31
|
-
const client = await getClient();
|
|
32
|
-
await confirmAndDelete({
|
|
33
|
-
id,
|
|
34
|
-
yes: args.yes,
|
|
35
|
-
promptMessage: `Delete transform test ${id}?`,
|
|
36
|
-
successMessage: `Deleted transform test ${id}.`,
|
|
37
|
-
abortMessage: `Aborted; transform test ${id} was not deleted.`,
|
|
38
|
-
deleteResource: () => client.transformTest.delete(id),
|
|
39
|
-
ctx
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
//#endregion
|
|
44
|
-
export { delete_default as default };
|
package/dist/get-BtTetWzm.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { H as outputFlags, U as profileFlag, u as renderItem, z as connectionFlags } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-arKqJqIT.mjs";
|
|
3
|
-
import { t as parseId } from "./parse-id-DmFJgpY6.mjs";
|
|
4
|
-
import { t as TransformTest } from "./transform-test-BjjCQ2xm.mjs";
|
|
5
|
-
import { t as transformTestView } from "./transform-test-gzDcbypy.mjs";
|
|
6
|
-
//#region src/commands/transform-test/get.ts
|
|
7
|
-
var get_default = defineMetabaseCommand({
|
|
8
|
-
meta: {
|
|
9
|
-
name: "get",
|
|
10
|
-
description: "Get a transform test by id"
|
|
11
|
-
},
|
|
12
|
-
details: "The compact form carries the id, transform, name and description. Pass --full for the `inputs` and `expectations` themselves, which is also the body to edit and send back to `update`.",
|
|
13
|
-
requires: ["transformTest.get"],
|
|
14
|
-
args: {
|
|
15
|
-
...outputFlags,
|
|
16
|
-
...profileFlag,
|
|
17
|
-
...connectionFlags,
|
|
18
|
-
id: {
|
|
19
|
-
type: "positional",
|
|
20
|
-
description: "Transform test id",
|
|
21
|
-
required: true
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
outputSchema: TransformTest,
|
|
25
|
-
examples: ["mb transform-test get 1", "mb transform-test get 1 --full --json"],
|
|
26
|
-
async run({ args, ctx, getClient }) {
|
|
27
|
-
const id = parseId(args.id);
|
|
28
|
-
renderItem(await (await getClient()).transformTest.get(id), transformTestView, ctx);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
//#endregion
|
|
32
|
-
export { get_default as default };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { t as defineCommandGroup } from "./group-YQQ5GIcP.mjs";
|
|
2
|
-
//#region src/commands/git-sync/index.ts
|
|
3
|
-
var git_sync_default = defineCommandGroup({
|
|
4
|
-
name: "git-sync",
|
|
5
|
-
description: "Sync Metabase content with a git remote",
|
|
6
|
-
skills: [{
|
|
7
|
-
skill: "git-sync",
|
|
8
|
-
purpose: "import/export round-trip and dirty checks"
|
|
9
|
-
}],
|
|
10
|
-
subCommands: {
|
|
11
|
-
status: () => import("./status-CXouQJ31.mjs").then((mod) => mod.default),
|
|
12
|
-
"is-dirty": () => import("./is-dirty-C5ipqd4v.mjs").then((mod) => mod.default),
|
|
13
|
-
"has-remote-changes": () => import("./has-remote-changes-i-3MVxat.mjs").then((mod) => mod.default),
|
|
14
|
-
dirty: () => import("./dirty-k-JmGLsS.mjs").then((mod) => mod.default),
|
|
15
|
-
"current-task": () => import("./current-task-BMt2NeqV.mjs").then((mod) => mod.default),
|
|
16
|
-
"cancel-task": () => import("./cancel-task-CqExODVm.mjs").then((mod) => mod.default),
|
|
17
|
-
wait: () => import("./wait-C-ovOTAZ.mjs").then((mod) => mod.default),
|
|
18
|
-
import: () => import("./import-DWEKejya.mjs").then((mod) => mod.default),
|
|
19
|
-
export: () => import("./export-Dq6ecU8h.mjs").then((mod) => mod.default),
|
|
20
|
-
stash: () => import("./stash-DdheS0Ad.mjs").then((mod) => mod.default),
|
|
21
|
-
branches: () => import("./branches-D5YLVFDK.mjs").then((mod) => mod.default),
|
|
22
|
-
"create-branch": () => import("./create-branch-BN5iH-GM.mjs").then((mod) => mod.default),
|
|
23
|
-
"add-collection": () => import("./add-collection-73X1DmCM.mjs").then((mod) => mod.default),
|
|
24
|
-
"remove-collection": () => import("./remove-collection-D3yvKH3e.mjs").then((mod) => mod.default)
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
//#endregion
|
|
28
|
-
export { git_sync_default as default };
|
package/dist/list-CHuhMXet.mjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { B as listFlags, G as listEnvelopeSchema, H as outputFlags, U as profileFlag, d as renderList, z as connectionFlags } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-arKqJqIT.mjs";
|
|
3
|
-
import { t as parseId } from "./parse-id-DmFJgpY6.mjs";
|
|
4
|
-
import { n as windowList } from "./window-DSb1tqSe.mjs";
|
|
5
|
-
import { n as TransformTestCompact } from "./transform-test-BjjCQ2xm.mjs";
|
|
6
|
-
import { t as transformTestView } from "./transform-test-gzDcbypy.mjs";
|
|
7
|
-
//#region src/commands/transform-test/list.ts
|
|
8
|
-
const TransformTestListEnvelope = listEnvelopeSchema(TransformTestCompact);
|
|
9
|
-
var list_default = defineMetabaseCommand({
|
|
10
|
-
meta: {
|
|
11
|
-
name: "list",
|
|
12
|
-
description: "List transform tests"
|
|
13
|
-
},
|
|
14
|
-
requires: ["transformTest.list"],
|
|
15
|
-
args: {
|
|
16
|
-
...outputFlags,
|
|
17
|
-
...listFlags,
|
|
18
|
-
...profileFlag,
|
|
19
|
-
...connectionFlags,
|
|
20
|
-
transform: {
|
|
21
|
-
type: "string",
|
|
22
|
-
description: "Only the tests of this transform id"
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
outputSchema: TransformTestListEnvelope,
|
|
26
|
-
examples: ["mb transform-test list", "mb transform-test list --transform 1 --json"],
|
|
27
|
-
async run({ args, ctx, getClient }) {
|
|
28
|
-
const client = await getClient();
|
|
29
|
-
const transformId = args.transform === void 0 ? void 0 : parseId(args.transform);
|
|
30
|
-
const { data } = await client.transformTest.list({ "transform-id": transformId });
|
|
31
|
-
renderList(windowList(data, ctx.range), transformTestView, ctx);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
//#endregion
|
|
35
|
-
export { list_default as default };
|
package/dist/run-DlO1J1Sx.mjs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { H as outputFlags, U as profileFlag, p as renderSummary, z as connectionFlags } from "./cli.mjs";
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-arKqJqIT.mjs";
|
|
3
|
-
import { t as parseId } from "./parse-id-DmFJgpY6.mjs";
|
|
4
|
-
import { i as TransformTestRunResult } from "./transform-test-BjjCQ2xm.mjs";
|
|
5
|
-
//#region src/commands/transform-test/run.ts
|
|
6
|
-
const transformTestRunResultView = {
|
|
7
|
-
compactPick: TransformTestRunResult,
|
|
8
|
-
tableColumns: [{
|
|
9
|
-
key: "status",
|
|
10
|
-
label: "Status"
|
|
11
|
-
}]
|
|
12
|
-
};
|
|
13
|
-
function namesOf(expectations, status) {
|
|
14
|
-
return expectations.filter((expectation) => expectation.status === status).map((e) => e.name);
|
|
15
|
-
}
|
|
16
|
-
function summaryLine(id, result) {
|
|
17
|
-
if (result.status === "passed") return `Transform test ${id} passed ${result.expectations.length} expectation(s).`;
|
|
18
|
-
const failed = namesOf(result.expectations, "failed");
|
|
19
|
-
const errored = namesOf(result.expectations, "error");
|
|
20
|
-
const parts = [failed.length > 0 ? `failed: ${failed.join(", ")}` : null, errored.length > 0 ? `could not run: ${errored.join(", ")}` : null].filter((part) => part !== null);
|
|
21
|
-
return `Transform test ${id} ${result.status} — ${parts.join("; ")}.`;
|
|
22
|
-
}
|
|
23
|
-
var run_default = defineMetabaseCommand({
|
|
24
|
-
meta: {
|
|
25
|
-
name: "run",
|
|
26
|
-
description: "Run a transform test by id"
|
|
27
|
-
},
|
|
28
|
-
details: "Runs the transform against temp tables built from the test's inputs, checks every expectation against its output, and drops the temp tables. Nothing reads or writes a real table. A failing expectation exits non-zero; --json reports what each expectation found, including the rows a comparison disagreed on.",
|
|
29
|
-
requires: ["transformTest.run"],
|
|
30
|
-
args: {
|
|
31
|
-
...outputFlags,
|
|
32
|
-
...profileFlag,
|
|
33
|
-
...connectionFlags,
|
|
34
|
-
id: {
|
|
35
|
-
type: "positional",
|
|
36
|
-
description: "Transform test id",
|
|
37
|
-
required: true
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
outputSchema: TransformTestRunResult,
|
|
41
|
-
examples: ["mb transform-test run 1", "mb transform-test run 1 --json"],
|
|
42
|
-
async run({ args, ctx, getClient }) {
|
|
43
|
-
const id = parseId(args.id);
|
|
44
|
-
const result = await (await getClient()).transformTest.run(id);
|
|
45
|
-
renderSummary(result, transformTestRunResultView, summaryLine(id, result), ctx);
|
|
46
|
-
if (result.status !== "passed") throw new Error(`transform test ${id} ${result.status}`);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
//#endregion
|
|
50
|
-
export { run_default as default };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { t as defineCommandGroup } from "./group-YQQ5GIcP.mjs";
|
|
2
|
-
//#region src/commands/transform-job/index.ts
|
|
3
|
-
var transform_job_default = defineCommandGroup({
|
|
4
|
-
name: "transform-job",
|
|
5
|
-
description: "Manage Metabase transform jobs",
|
|
6
|
-
skills: [{
|
|
7
|
-
skill: "transform",
|
|
8
|
-
purpose: "tag-driven job schedules"
|
|
9
|
-
}],
|
|
10
|
-
subCommands: {
|
|
11
|
-
list: () => import("./list-CgH-H-O6.mjs").then((mod) => mod.default),
|
|
12
|
-
get: () => import("./get-D4oGhZWX.mjs").then((mod) => mod.default),
|
|
13
|
-
create: () => import("./create-DJm0YuLW.mjs").then((mod) => mod.default),
|
|
14
|
-
update: () => import("./update-Dz47cKBk.mjs").then((mod) => mod.default),
|
|
15
|
-
delete: () => import("./delete-Ur7b11no.mjs").then((mod) => mod.default),
|
|
16
|
-
run: () => import("./run-B2f_omHu.mjs").then((mod) => mod.default),
|
|
17
|
-
transforms: () => import("./transforms-CijX3VE7.mjs").then((mod) => mod.default),
|
|
18
|
-
"set-active": () => import("./set-active-RrvWR9NY.mjs").then((mod) => mod.default)
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
//#endregion
|
|
22
|
-
export { transform_job_default as default };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { t as defineCommandGroup } from "./group-YQQ5GIcP.mjs";
|
|
2
|
-
//#region src/commands/transform/index.ts
|
|
3
|
-
var transform_default = defineCommandGroup({
|
|
4
|
-
name: "transform",
|
|
5
|
-
description: "Manage Metabase transforms",
|
|
6
|
-
skills: [{
|
|
7
|
-
skill: "transform",
|
|
8
|
-
purpose: "body shape, run-with-wait, iterate"
|
|
9
|
-
}, {
|
|
10
|
-
skill: "mbql",
|
|
11
|
-
purpose: "MBQL source.query bodies"
|
|
12
|
-
}],
|
|
13
|
-
subCommands: {
|
|
14
|
-
list: () => import("./list-DI820W6w.mjs").then((mod) => mod.default),
|
|
15
|
-
get: () => import("./get-7xTeNGAo.mjs").then((mod) => mod.default),
|
|
16
|
-
dependencies: () => import("./dependencies-XDVLBwko.mjs").then((mod) => mod.default),
|
|
17
|
-
create: () => import("./create-BJad6MR82.mjs").then((mod) => mod.default),
|
|
18
|
-
update: () => import("./update-KSHnb6vB.mjs").then((mod) => mod.default),
|
|
19
|
-
delete: () => import("./delete-D2bUV6uo.mjs").then((mod) => mod.default),
|
|
20
|
-
"delete-table": () => import("./delete-table-Dd8X573t.mjs").then((mod) => mod.default),
|
|
21
|
-
run: () => import("./run-yX2dtmE5.mjs").then((mod) => mod.default),
|
|
22
|
-
cancel: () => import("./cancel-DeRIq1YJ.mjs").then((mod) => mod.default),
|
|
23
|
-
"get-run": () => import("./get-run-CZdDqfUj.mjs").then((mod) => mod.default),
|
|
24
|
-
runs: () => import("./runs-DzUO45wU.mjs").then((mod) => mod.default)
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
//#endregion
|
|
28
|
-
export { transform_default as default };
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
//#region ../client/src/domain/transform-test.ts
|
|
3
|
-
const TransformTestTable = z.object({
|
|
4
|
-
schema: z.string().min(1).nullable().optional(),
|
|
5
|
-
name: z.string().min(1)
|
|
6
|
-
}).loose();
|
|
7
|
-
const TransformTestColumn = z.object({
|
|
8
|
-
name: z.string().min(1),
|
|
9
|
-
cast_type: z.string().min(1)
|
|
10
|
-
}).loose();
|
|
11
|
-
const TransformTestCell = z.union([
|
|
12
|
-
z.boolean(),
|
|
13
|
-
z.number(),
|
|
14
|
-
z.string(),
|
|
15
|
-
z.null()
|
|
16
|
-
]);
|
|
17
|
-
const TransformTestRow = z.record(z.string(), TransformTestCell);
|
|
18
|
-
const TransformTestSqlInput = z.object({
|
|
19
|
-
table: TransformTestTable,
|
|
20
|
-
format: z.literal("sql"),
|
|
21
|
-
sql: z.string().min(1)
|
|
22
|
-
}).loose();
|
|
23
|
-
const TransformTestRowsInput = z.object({
|
|
24
|
-
table: TransformTestTable,
|
|
25
|
-
format: z.literal("rows"),
|
|
26
|
-
columns: z.array(TransformTestColumn).min(1),
|
|
27
|
-
rows: z.array(TransformTestRow)
|
|
28
|
-
}).loose();
|
|
29
|
-
const TransformTestInput = z.discriminatedUnion("format", [TransformTestSqlInput, TransformTestRowsInput]);
|
|
30
|
-
const TransformTestEqualsSqlExpectation = z.object({
|
|
31
|
-
type: z.literal("equals"),
|
|
32
|
-
name: z.string().min(1),
|
|
33
|
-
format: z.literal("sql"),
|
|
34
|
-
sql: z.string().min(1)
|
|
35
|
-
}).loose();
|
|
36
|
-
const TransformTestEqualsRowsExpectation = z.object({
|
|
37
|
-
type: z.literal("equals"),
|
|
38
|
-
name: z.string().min(1),
|
|
39
|
-
format: z.literal("rows"),
|
|
40
|
-
columns: z.array(TransformTestColumn).min(1),
|
|
41
|
-
rows: z.array(TransformTestRow)
|
|
42
|
-
}).loose();
|
|
43
|
-
const TransformTestEqualsExpectation = z.discriminatedUnion("format", [TransformTestEqualsSqlExpectation, TransformTestEqualsRowsExpectation]);
|
|
44
|
-
const TransformTestEmptyExpectation = z.object({
|
|
45
|
-
type: z.literal("empty"),
|
|
46
|
-
name: z.string().min(1),
|
|
47
|
-
sql: z.string().min(1)
|
|
48
|
-
}).loose();
|
|
49
|
-
const TransformTestExpectation = z.discriminatedUnion("type", [TransformTestEqualsExpectation, TransformTestEmptyExpectation]);
|
|
50
|
-
const TransformTest = z.object({
|
|
51
|
-
id: z.number().int(),
|
|
52
|
-
entity_id: z.string(),
|
|
53
|
-
transform_id: z.number().int(),
|
|
54
|
-
creator_id: z.number().int(),
|
|
55
|
-
name: z.string(),
|
|
56
|
-
description: z.string().nullable(),
|
|
57
|
-
inputs: z.array(TransformTestInput),
|
|
58
|
-
expectations: z.array(TransformTestExpectation),
|
|
59
|
-
created_at: z.string(),
|
|
60
|
-
updated_at: z.string()
|
|
61
|
-
}).loose();
|
|
62
|
-
const TransformTestCompact = TransformTest.pick({
|
|
63
|
-
id: true,
|
|
64
|
-
transform_id: true,
|
|
65
|
-
name: true,
|
|
66
|
-
description: true
|
|
67
|
-
}).strip();
|
|
68
|
-
/**
|
|
69
|
-
* The server closes this map, so an unrecognized key is a 400 there. Refusing it here names the key
|
|
70
|
-
* instead: a body cloned from `get` has to shed `id`, `entity_id`, `creator_id`, `created_at` and
|
|
71
|
-
* `updated_at` before it can be sent back.
|
|
72
|
-
*/
|
|
73
|
-
const TransformTestCreateInput = z.object({
|
|
74
|
-
transform_id: z.number().int().positive(),
|
|
75
|
-
name: z.string().min(1),
|
|
76
|
-
description: z.string().nullable().optional(),
|
|
77
|
-
inputs: z.array(TransformTestInput),
|
|
78
|
-
expectations: z.array(TransformTestExpectation)
|
|
79
|
-
}).strict();
|
|
80
|
-
/** Closed for the same reason as [[TransformTestCreateInput]]; every field is optional. */
|
|
81
|
-
const TransformTestUpdateInput = z.object({
|
|
82
|
-
transform_id: z.number().int().positive().optional(),
|
|
83
|
-
name: z.string().min(1).optional(),
|
|
84
|
-
description: z.string().nullable().optional(),
|
|
85
|
-
inputs: z.array(TransformTestInput).optional(),
|
|
86
|
-
expectations: z.array(TransformTestExpectation).optional()
|
|
87
|
-
}).strict();
|
|
88
|
-
const TransformTestResultColumn = z.object({
|
|
89
|
-
name: z.string(),
|
|
90
|
-
database_type: z.string()
|
|
91
|
-
}).loose();
|
|
92
|
-
const TransformTestExpectationError = z.object({
|
|
93
|
-
type: z.string(),
|
|
94
|
-
message: z.string()
|
|
95
|
-
}).loose();
|
|
96
|
-
const TransformTestCellMismatch = z.object({
|
|
97
|
-
column: z.string(),
|
|
98
|
-
expected: TransformTestCell,
|
|
99
|
-
actual: TransformTestCell
|
|
100
|
-
}).loose();
|
|
101
|
-
const TransformTestRowCounts = z.object({
|
|
102
|
-
actual: z.number().int(),
|
|
103
|
-
expected: z.number().int()
|
|
104
|
-
}).loose();
|
|
105
|
-
const TransformTestEqualsFindings = z.object({
|
|
106
|
-
name: z.string(),
|
|
107
|
-
type: z.literal("equals"),
|
|
108
|
-
status: z.enum(["passed", "failed"]),
|
|
109
|
-
columns: z.array(TransformTestResultColumn),
|
|
110
|
-
"row-counts": TransformTestRowCounts,
|
|
111
|
-
"extra-rows": z.array(TransformTestRow),
|
|
112
|
-
"missing-rows": z.array(TransformTestRow),
|
|
113
|
-
"cell-mismatches": z.array(TransformTestCellMismatch),
|
|
114
|
-
truncated: z.number().int()
|
|
115
|
-
}).loose();
|
|
116
|
-
const TransformTestEqualsError = z.object({
|
|
117
|
-
name: z.string(),
|
|
118
|
-
type: z.literal("equals"),
|
|
119
|
-
status: z.literal("error"),
|
|
120
|
-
error: TransformTestExpectationError
|
|
121
|
-
}).loose();
|
|
122
|
-
const TransformTestEqualsResult = z.discriminatedUnion("status", [TransformTestEqualsFindings, TransformTestEqualsError]);
|
|
123
|
-
const TransformTestEmptyPassed = z.object({
|
|
124
|
-
name: z.string(),
|
|
125
|
-
type: z.literal("empty"),
|
|
126
|
-
status: z.literal("passed")
|
|
127
|
-
}).loose();
|
|
128
|
-
const TransformTestEmptyFailed = z.object({
|
|
129
|
-
name: z.string(),
|
|
130
|
-
type: z.literal("empty"),
|
|
131
|
-
status: z.literal("failed"),
|
|
132
|
-
columns: z.array(TransformTestResultColumn),
|
|
133
|
-
sample: z.array(TransformTestRow),
|
|
134
|
-
truncated: z.number().int()
|
|
135
|
-
}).loose();
|
|
136
|
-
const TransformTestEmptyError = z.object({
|
|
137
|
-
name: z.string(),
|
|
138
|
-
type: z.literal("empty"),
|
|
139
|
-
status: z.literal("error"),
|
|
140
|
-
error: TransformTestExpectationError
|
|
141
|
-
}).loose();
|
|
142
|
-
const TransformTestEmptyResult = z.discriminatedUnion("status", [
|
|
143
|
-
TransformTestEmptyPassed,
|
|
144
|
-
TransformTestEmptyFailed,
|
|
145
|
-
TransformTestEmptyError
|
|
146
|
-
]);
|
|
147
|
-
const TransformTestExpectationResult = z.discriminatedUnion("type", [TransformTestEqualsResult, TransformTestEmptyResult]);
|
|
148
|
-
const TransformTestRunResult = z.object({
|
|
149
|
-
status: z.enum(["passed", "failed"]),
|
|
150
|
-
expectations: z.array(TransformTestExpectationResult),
|
|
151
|
-
tables: z.record(z.string(), z.string())
|
|
152
|
-
}).loose();
|
|
153
|
-
z.enum([
|
|
154
|
-
"transform-test.unknown-column",
|
|
155
|
-
"transform-test.ambiguous-column",
|
|
156
|
-
"transform-test.missing-inputs",
|
|
157
|
-
"transform-test.unused-inputs",
|
|
158
|
-
"transform-test.duplicate-input-table",
|
|
159
|
-
"transform-test.unparseable-source",
|
|
160
|
-
"transform-test.unremapped-reference",
|
|
161
|
-
"transform-test.unsupported-transform",
|
|
162
|
-
"transform-test.unsupported-driver",
|
|
163
|
-
"transform-test.transform-failed",
|
|
164
|
-
"transform-test.setup-failed",
|
|
165
|
-
"transform-test.expectation-failed",
|
|
166
|
-
"transform-test.unsupported-format"
|
|
167
|
-
]);
|
|
168
|
-
//#endregion
|
|
169
|
-
export { TransformTestUpdateInput as a, TransformTestRunResult as i, TransformTestCompact as n, TransformTestCreateInput as r, TransformTest as t };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { t as defineCommandGroup } from "./group-YQQ5GIcP.mjs";
|
|
2
|
-
//#region src/commands/transform-test/index.ts
|
|
3
|
-
var transform_test_default = defineCommandGroup({
|
|
4
|
-
name: "transform-test",
|
|
5
|
-
description: "Manage transform tests — fixtures and expectations run against temp tables",
|
|
6
|
-
subCommands: {
|
|
7
|
-
list: () => import("./list-CHuhMXet.mjs").then((mod) => mod.default),
|
|
8
|
-
get: () => import("./get-BtTetWzm.mjs").then((mod) => mod.default),
|
|
9
|
-
create: () => import("./create-uanpKsPo.mjs").then((mod) => mod.default),
|
|
10
|
-
update: () => import("./update-Ci8YL4_2.mjs").then((mod) => mod.default),
|
|
11
|
-
delete: () => import("./delete-DZ_ICQug.mjs").then((mod) => mod.default),
|
|
12
|
-
run: () => import("./run-DlO1J1Sx.mjs").then((mod) => mod.default)
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
//#endregion
|
|
16
|
-
export { transform_test_default as default };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { n as TransformTestCompact } from "./transform-test-BjjCQ2xm.mjs";
|
|
2
|
-
//#region src/output/views/transform-test.ts
|
|
3
|
-
const transformTestView = {
|
|
4
|
-
compactPick: TransformTestCompact,
|
|
5
|
-
tableColumns: [
|
|
6
|
-
{
|
|
7
|
-
key: "id",
|
|
8
|
-
label: "ID"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
key: "transform_id",
|
|
12
|
-
label: "Transform"
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
key: "name",
|
|
16
|
-
label: "Name"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
key: "description",
|
|
20
|
-
label: "Description"
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
};
|
|
24
|
-
//#endregion
|
|
25
|
-
export { transformTestView as t };
|