@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.
Files changed (196) hide show
  1. package/dist/{add-collection-73X1DmCM.mjs → add-collection-BjVAdZ1n.mjs} +2 -2
  2. package/dist/{alert-BB38lWSL.mjs → alert-DCLhfwdv.mjs} +6 -6
  3. package/dist/{alerts-DxyzqLSU.mjs → alerts-DRin_wt2.mjs} +3 -3
  4. package/dist/{append-CHme1Enm.mjs → append-DQ9rPJHZ.mjs} +2 -2
  5. package/dist/{archive-BGiDxu8O.mjs → archive-1YVo-Wsu.mjs} +2 -2
  6. package/dist/{archive-CP5Hlqjw.mjs → archive-BPCgmLcV.mjs} +2 -2
  7. package/dist/{archive-DBcxZwLd.mjs → archive-BVRKE9Ev.mjs} +2 -2
  8. package/dist/{archive-DPL1qOuL.mjs → archive-BzVxRqpL.mjs} +2 -2
  9. package/dist/{archive-Czo5T0Lp.mjs → archive-COFQAHAL.mjs} +2 -2
  10. package/dist/{archive-CqKqNdUh.mjs → archive-D3yPvUtz.mjs} +2 -2
  11. package/dist/{archive-eS-XA74p.mjs → archive-D6xzHaM3.mjs} +2 -2
  12. package/dist/{archive-Cq3fnc0v2.mjs → archive-HeRygdKz2.mjs} +2 -2
  13. package/dist/{archive-BMyvyf62.mjs → archive-_c-ISZmi.mjs} +2 -2
  14. package/dist/{archive-C4Y2B58q.mjs → archive-o5cWV3vZ.mjs} +2 -2
  15. package/dist/{archive-DKFPJ9j3.mjs → archive-xcgoVPwv.mjs} +2 -2
  16. package/dist/{auth-6YyB0HNB.mjs → auth-DJn5T6zA.mjs} +4 -4
  17. package/dist/{body-OjAWKVaU.mjs → body-Cu94pH4P.mjs} +1 -1
  18. package/dist/{branches-D5YLVFDK.mjs → branches-CUyPxeeW.mjs} +1 -1
  19. package/dist/{cancel-DeRIq1YJ.mjs → cancel-BNuVls58.mjs} +2 -2
  20. package/dist/{cancel-task-CqExODVm.mjs → cancel-task-DUmlQQpi.mjs} +1 -1
  21. package/dist/{card-BMSqofd7.mjs → card-ByOzVxpI.mjs} +7 -7
  22. package/dist/{cards-B813G9I5.mjs → cards-_gbvw3wp.mjs} +2 -2
  23. package/dist/cli.mjs +31 -32
  24. package/dist/{client-cJ7aw0Gt.mjs → client-BnK0evYf.mjs} +162 -2
  25. package/dist/{collection-BfNg7tEg.mjs → collection-BGbW7u_Q.mjs} +6 -6
  26. package/dist/{collection-namespace-CVzDgJV0.mjs → collection-namespace-DM90lA8C.mjs} +1 -1
  27. package/dist/{content-translation-QKWt9l76.mjs → content-translation-CqB3peU9.mjs} +2 -2
  28. package/dist/{create-CoFg1p6m.mjs → create-B48rmY8v.mjs} +2 -2
  29. package/dist/{create-DEBgYRlM.mjs → create-B7S5fCkD.mjs} +2 -2
  30. package/dist/{create-CvpeAcFc.mjs → create-BIUVvIGH.mjs} +2 -2
  31. package/dist/{create-bvpl6Fn5.mjs → create-BMKuihoI.mjs} +3 -3
  32. package/dist/{create-CWGsiFvU.mjs → create-BSvTs-EV.mjs} +2 -2
  33. package/dist/{create-BLiB2xqo.mjs → create-CUHpxANR.mjs} +2 -2
  34. package/dist/{create-DmKwDQCY2.mjs → create-Cm9Z-rfe2.mjs} +2 -2
  35. package/dist/{create-BWp6L_dW.mjs → create-CnJKj9Nl.mjs} +2 -2
  36. package/dist/{create-CMV3qlzJ.mjs → create-CwXUMOMd.mjs} +2 -2
  37. package/dist/{create-4UnoQvsy.mjs → create-D4Y69cDF.mjs} +2 -2
  38. package/dist/{create-Bef5eBCA.mjs → create-DMVw9nrZ.mjs} +2 -2
  39. package/dist/{create-BJad6MR82.mjs → create-DNx9TGHs.mjs} +3 -3
  40. package/dist/{create-CvIeb1NU.mjs → create-DVo8-IzZ.mjs} +2 -2
  41. package/dist/{create-D50TxVTk.mjs → create-IFjwHs0G.mjs} +1 -1
  42. package/dist/{create-branch-BN5iH-GM.mjs → create-branch-Cw-uXows.mjs} +1 -1
  43. package/dist/{create-DJm0YuLW.mjs → create-va8bByVt.mjs} +2 -2
  44. package/dist/{csv-BhuX9fwh.mjs → csv-CaKx1oFZ.mjs} +2 -2
  45. package/dist/{current-task-BMt2NeqV.mjs → current-task-lGh69Z1i.mjs} +1 -1
  46. package/dist/{dashboard-Ct_ajSYI.mjs → dashboard-Bzjz2v6u.mjs} +9 -9
  47. package/dist/{db-B_LW2VE-.mjs → db-BRHPjshe.mjs} +6 -6
  48. package/dist/{delete-CowGO4rh.mjs → delete-BxBadE3q.mjs} +2 -2
  49. package/dist/{delete-D2bUV6uo.mjs → delete-CQWCfqHf.mjs} +2 -2
  50. package/dist/{delete-D0f7VatX.mjs → delete-Ci0aDYpf.mjs} +2 -2
  51. package/dist/{delete-Ur7b11no.mjs → delete-DMETa-37.mjs} +2 -2
  52. package/dist/{delete-BOcPK_H9.mjs → delete-G6EiGn2Q.mjs} +2 -2
  53. package/dist/{delete-table-Dd8X573t.mjs → delete-table-N4rZtt1T.mjs} +2 -2
  54. package/dist/{dependencies-XDVLBwko.mjs → dependencies-edN0P1SS.mjs} +2 -2
  55. package/dist/{dirty-k-JmGLsS.mjs → dirty-U51bMoCP.mjs} +1 -1
  56. package/dist/{document-BW9iow8R.mjs → document-DqJ7Cysa.mjs} +5 -5
  57. package/dist/{download-CQjPIYDO.mjs → download-BJA6k-e6.mjs} +1 -1
  58. package/dist/{eid-CNTKDgwj.mjs → eid-BtlRU1E0.mjs} +2 -2
  59. package/dist/{events-BshWlkDp.mjs → events-B5rnOo-L.mjs} +2 -2
  60. package/dist/{export-Dq6ecU8h.mjs → export-DO2josC0.mjs} +2 -2
  61. package/dist/{field-Bo2ISMO4.mjs → field-CHZByaXa.mjs} +4 -4
  62. package/dist/{fields-CVctqn5G.mjs → fields-zQ6O_W_H.mjs} +2 -2
  63. package/dist/{get-RslzBaXx.mjs → get-93wuhTn2.mjs} +1 -1
  64. package/dist/{get-8b5Sh50q.mjs → get-BDrmBZ1z.mjs} +2 -2
  65. package/dist/{get-BD81MHl_.mjs → get-BLcS4il2.mjs} +2 -2
  66. package/dist/{get-CrpwxWOV.mjs → get-BLjcCXp8.mjs} +2 -2
  67. package/dist/{get-Dr-U321T2.mjs → get-BSoMWp4t2.mjs} +2 -2
  68. package/dist/{get-Dw7jAno3.mjs → get-CG6G-mzV.mjs} +2 -2
  69. package/dist/{get-PWhOdz1z.mjs → get-CTp5l7aU.mjs} +1 -1
  70. package/dist/{get-CTPvdcud.mjs → get-CeSQptdl.mjs} +2 -2
  71. package/dist/{get-BvgEF--n.mjs → get-CekXFP3x.mjs} +2 -2
  72. package/dist/{get-Bl3OmlBP.mjs → get-Cf6a4fFN.mjs} +2 -2
  73. package/dist/{get-7xTeNGAo.mjs → get-CwiJWeH4.mjs} +2 -2
  74. package/dist/{get-CO6X4nZH.mjs → get-DC_huYD8.mjs} +3 -3
  75. package/dist/{get-Df6cGHCM.mjs → get-DXwlZjw0.mjs} +2 -2
  76. package/dist/{get-D4oGhZWX.mjs → get-Dg-S07ri.mjs} +2 -2
  77. package/dist/{get-DfMVlz64.mjs → get-DhpMuTSt.mjs} +1 -1
  78. package/dist/{get-C5sWciaE.mjs → get-EFsmL4le.mjs} +2 -2
  79. package/dist/{get-wjIgUlNl.mjs → get-is8x5f2n.mjs} +2 -2
  80. package/dist/{get-run-CZdDqfUj.mjs → get-run-DwY4sFGy.mjs} +2 -2
  81. package/dist/{get-B4RgW-VT.mjs → get-xPv7e5Ez.mjs} +2 -2
  82. package/dist/{get-BvSA_mmf.mjs → get-yHIEezeG.mjs} +2 -2
  83. package/dist/git-sync-NhfLSZA6.mjs +28 -0
  84. package/dist/{has-remote-changes-i-3MVxat.mjs → has-remote-changes-DE2_14FK.mjs} +1 -1
  85. package/dist/{import-DWEKejya.mjs → import-Cs7wk058.mjs} +2 -2
  86. package/dist/{is-dirty-C5ipqd4v.mjs → is-dirty-XqDfqXGi.mjs} +1 -1
  87. package/dist/{items-hKJ2ZDwy.mjs → items-BloAjPwA.mjs} +1 -1
  88. package/dist/{library-B7_04UVK.mjs → library-Dgq_5BFh.mjs} +4 -4
  89. package/dist/{list-Bs7_Rysg.mjs → list-3ErmGdY0.mjs} +1 -1
  90. package/dist/{list-DfRqNH1N.mjs → list-BZnf3RmA.mjs} +1 -1
  91. package/dist/{list-oX2SMzxZ.mjs → list-BfLo1xI8.mjs} +1 -1
  92. package/dist/{list-CgH-H-O6.mjs → list-Bzm5mXRo.mjs} +1 -1
  93. package/dist/{list-DKcC4cm0.mjs → list-CUJ1wem9.mjs} +1 -1
  94. package/dist/{list-Cen-7uTo.mjs → list-CUXlZiS1.mjs} +1 -1
  95. package/dist/{list-CjNXskB4.mjs → list-CZCaqPoo.mjs} +1 -1
  96. package/dist/{list-DI820W6w.mjs → list-CghNKfYJ.mjs} +1 -1
  97. package/dist/{list-1vdClKSE.mjs → list-D04uiS3F.mjs} +1 -1
  98. package/dist/{list-DjwnsyXM.mjs → list-D9d5ocYi.mjs} +3 -3
  99. package/dist/{list-DKZnQ4Ts.mjs → list-DboUvg-Y.mjs} +1 -1
  100. package/dist/{list-6myofqMv.mjs → list-DgteFn01.mjs} +2 -2
  101. package/dist/{list-CmFh1GQ_.mjs → list-DuJezLm_.mjs} +1 -1
  102. package/dist/{list-CLZU_EOf.mjs → list-VzrtA9lt.mjs} +1 -1
  103. package/dist/{list-VNC-_E59.mjs → list-f8Csdjyc.mjs} +1 -1
  104. package/dist/{list-eKDT1XXk.mjs → list-sdCIS2Df.mjs} +3 -3
  105. package/dist/{list-B-9QOX9Y.mjs → list-vsXIMssK.mjs} +1 -1
  106. package/dist/{list-D6tTvYUP.mjs → list-yV6CyPzn.mjs} +1 -1
  107. package/dist/{login-DumZaWXK.mjs → login-Vw51Gts5.mjs} +3 -3
  108. package/dist/{logout-BsXPRc-3.mjs → logout-BDIqoVhv.mjs} +1 -1
  109. package/dist/{measure-BFxkbAoa.mjs → measure-LY9Tp9QZ.mjs} +5 -5
  110. package/dist/{parameter-values-CoF9Hx1p.mjs → parameter-values-DWjmO7Ai.mjs} +2 -2
  111. package/dist/{parse-id-DmFJgpY6.mjs → parse-id-whJX4DAb.mjs} +1 -1
  112. package/dist/{path-BQ4lRDyN.mjs → path-BUUAGYO5.mjs} +2 -2
  113. package/dist/{preflight-BTQe4swo.mjs → preflight-DcULqq8E.mjs} +1 -1
  114. package/dist/{publish-CFB2Cc5A.mjs → publish-qVFmJQ1E.mjs} +2 -2
  115. package/dist/{query-CV2KCS5O.mjs → query-BPtIy79s.mjs} +2 -2
  116. package/dist/{query-BJbUnAHf.mjs → query-Cq1lmqL5.mjs} +2 -2
  117. package/dist/{remove-collection-D3yvKH3e.mjs → remove-collection-DBqh2Lqm.mjs} +2 -2
  118. package/dist/{render-BJRCs7rA.mjs → render-Gx1hR7IF.mjs} +1 -1
  119. package/dist/{replace-uj4WTqx_.mjs → replace-CujInVY9.mjs} +2 -2
  120. package/dist/{rescan-values-CzxQU318.mjs → rescan-values-HypqBCSK.mjs} +2 -2
  121. package/dist/{run-B2f_omHu.mjs → run-DEkQSOQa.mjs} +2 -2
  122. package/dist/{run-yX2dtmE5.mjs → run-b3jyF29q.mjs} +3 -3
  123. package/dist/{runs-DzUO45wU.mjs → runs-GHqHLGy4.mjs} +2 -2
  124. package/dist/{runtime-arKqJqIT.mjs → runtime-nCPku2nN.mjs} +1 -1
  125. package/dist/{schema-tables-DZCNzuQ6.mjs → schema-tables-B5L05Y1L.mjs} +2 -2
  126. package/dist/{schemas-2ejqaVsG.mjs → schemas-Clx26p_4.mjs} +2 -2
  127. package/dist/{search-DcihauDZ.mjs → search-DxiuY5EV.mjs} +2 -2
  128. package/dist/{segment-BQT2poPG.mjs → segment-DiRJcbam.mjs} +5 -5
  129. package/dist/{selectors-BzestDld.mjs → selectors-rEFuyXPZ.mjs} +2 -2
  130. package/dist/{send-DMxoLFo7.mjs → send-DIHkDNBN.mjs} +2 -2
  131. package/dist/{set-CDmiD0vv.mjs → set-D77qUZML.mjs} +2 -2
  132. package/dist/{set-active-RrvWR9NY.mjs → set-active-DCdFgD0O.mjs} +1 -1
  133. package/dist/{setting-BiBLCcxz.mjs → setting-DR9bj232.mjs} +3 -3
  134. package/dist/{setup-DYsTzkWO.mjs → setup-DGa2LLEp.mjs} +2 -2
  135. package/dist/{skill-list-D9_1Pmt7.mjs → skill-list-DAvGGHzS.mjs} +1 -1
  136. package/dist/{skills-C3bxxC6a.mjs → skills-CCn7cyMP.mjs} +3 -3
  137. package/dist/{skills-BPHXUfeL.mjs → skills-CqtNuSXM.mjs} +1 -1
  138. package/dist/{snippet-BtfxE60H.mjs → snippet-g9JTDxqu.mjs} +5 -5
  139. package/dist/{stash-DdheS0Ad.mjs → stash-BTtsV0AG.mjs} +2 -2
  140. package/dist/{status-CXouQJ31.mjs → status-CW7Dt-nV.mjs} +1 -1
  141. package/dist/{status-BuIzXRX1.mjs → status-XgSS3StV.mjs} +2 -2
  142. package/dist/{subscription-CJ8Igs1U.mjs → subscription-CofRU47d.mjs} +5 -5
  143. package/dist/{subscriptions-D0NpGvCQ.mjs → subscriptions-DCuuPF6U.mjs} +3 -3
  144. package/dist/{summary-D04S8gGj.mjs → summary-uGlgKE3C.mjs} +2 -2
  145. package/dist/{sync-schema-DrA5zkdl.mjs → sync-schema-Cu9rD3eH.mjs} +3 -3
  146. package/dist/{table-Dntbz7Q2.mjs → table-Di-EY7pg.mjs} +4 -4
  147. package/dist/{timeline-8jwsldo3.mjs → timeline-D7EsWZm6.mjs} +7 -7
  148. package/dist/{timeline-event-BbB1xEdI.mjs → timeline-event-D-h0A_oh.mjs} +5 -5
  149. package/dist/transform-8XK1LIgC.mjs +28 -0
  150. package/dist/transform-job-CTizQkWy.mjs +22 -0
  151. package/dist/{transform-tag-PjryheLF.mjs → transform-tag-BLp_p9J-.mjs} +4 -4
  152. package/dist/{transforms-CijX3VE7.mjs → transforms-n2IwEcbU.mjs} +2 -2
  153. package/dist/{tree-Cmb3O6rH.mjs → tree-cqxiDh2b.mjs} +1 -1
  154. package/dist/{unpublish-DkP_AcK5.mjs → unpublish-DVQCAa3g.mjs} +2 -2
  155. package/dist/{update-BFyRBc-H.mjs → update-B7CikkI0.mjs} +4 -4
  156. package/dist/{update-CtLbFCd_.mjs → update-C05J2nZ2.mjs} +3 -3
  157. package/dist/{update-D8htjzNJ.mjs → update-CAsqNhDC.mjs} +3 -3
  158. package/dist/{update-D9kOTr0n.mjs → update-CKDRuduL.mjs} +3 -3
  159. package/dist/{update-COcx61Ur.mjs → update-ChpOukqq.mjs} +3 -3
  160. package/dist/{update-DPTio6i1.mjs → update-CnkPYL2i.mjs} +3 -3
  161. package/dist/{update-KSHnb6vB.mjs → update-D4ggtuG4.mjs} +4 -4
  162. package/dist/{update-DlWB9s0v.mjs → update-D9H6Lh5U.mjs} +3 -3
  163. package/dist/{update-8UmD1prT.mjs → update-DFdBeJwc.mjs} +3 -3
  164. package/dist/{update-FCP5Lop2.mjs → update-DKO9HF1f.mjs} +3 -3
  165. package/dist/{update-BrXGg3QO.mjs → update-DScUzKLI.mjs} +3 -3
  166. package/dist/{update-DubrpPbz.mjs → update-DffrdV4b.mjs} +3 -3
  167. package/dist/{update-C91m9YAR.mjs → update-NGq0yXZk.mjs} +3 -3
  168. package/dist/{update-dashcard-BlibHa5o.mjs → update-dashcard-DvPqLJ3N.mjs} +3 -3
  169. package/dist/{update-D6Zzvc7F.mjs → update-oQeQyqKO.mjs} +3 -3
  170. package/dist/{update-Dz47cKBk.mjs → update-rFRPLlb6.mjs} +3 -3
  171. package/dist/{upgrade-EwL6wPSY.mjs → upgrade-BRgw0fvn.mjs} +1 -1
  172. package/dist/{upload-D0KaTqUE.mjs → upload-BrfbcbBW.mjs} +1 -1
  173. package/dist/{upload-BZshRJIM.mjs → upload-VXBFKzLT.mjs} +3 -3
  174. package/dist/{uuid-DjKLDIVE.mjs → uuid-B4eij1d7.mjs} +1 -1
  175. package/dist/{values-Dc9612_L.mjs → values-xgOftPq5.mjs} +2 -2
  176. package/dist/{verify-DVN1eqXZ.mjs → verify-DTOA_wVM.mjs} +2 -2
  177. package/dist/{wait-C-ovOTAZ.mjs → wait-BjeFgR13.mjs} +2 -2
  178. package/dist/{wait-flags-BQNmuvIj.mjs → wait-flags-BCeCnaz3.mjs} +1 -1
  179. package/package.json +1 -1
  180. package/skill-data/core/SKILL.md +8 -14
  181. package/skill-data/transform/SKILL.md +1 -63
  182. package/dist/create-uanpKsPo.mjs +0 -34
  183. package/dist/delete-DZ_ICQug.mjs +0 -44
  184. package/dist/get-BtTetWzm.mjs +0 -32
  185. package/dist/git-sync-BmoRk0UV.mjs +0 -28
  186. package/dist/list-CHuhMXet.mjs +0 -35
  187. package/dist/run-DlO1J1Sx.mjs +0 -50
  188. package/dist/transform-job-B-1YAbvy.mjs +0 -22
  189. package/dist/transform-m6s4kkWU.mjs +0 -28
  190. package/dist/transform-test-BjjCQ2xm.mjs +0 -169
  191. package/dist/transform-test-DSTkKKNC.mjs +0 -16
  192. package/dist/transform-test-gzDcbypy.mjs +0 -25
  193. package/dist/update-Ci8YL4_2.mjs +0 -41
  194. package/skill-data/transform-test-plan/SKILL.md +0 -171
  195. package/skill-data/transform-test-plan/references/checklist.md +0 -81
  196. package/skill-data/transform-test-plan/references/checks.md +0 -260
@@ -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: CRUD on every resource, query and transform execution, search, git-sync (representations ↔ instance), and entity-id translation.
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 | transform-test | alert | subscription | setting
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
- Only what `--help` does _not_ tell you: footguns and non-obvious behaviors.
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, transform tests (fixtures and expectations run against temp tables), 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", "test a 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 …` / `mb transform-test …`.
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
@@ -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 };
@@ -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 };
@@ -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 };
@@ -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 };
@@ -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 };