@metabase/cli 0.1.0 → 0.1.1

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 (187) hide show
  1. package/README.md +972 -57
  2. package/dist/add-collection--zwkmE1S.mjs +11 -0
  3. package/dist/add-collection-B1qe0D1U.mjs +54 -0
  4. package/dist/api-key-gzCbKDjL.mjs +13 -0
  5. package/dist/archive-CitmlD1e.mjs +39 -0
  6. package/dist/{archive-CsWeHXle.mjs → archive-CnhWegtR.mjs} +7 -4
  7. package/dist/archive-DQjBOXnx.mjs +44 -0
  8. package/dist/archive-Ni8-lQ1Y.mjs +44 -0
  9. package/dist/auth-BPjsrFxM.mjs +19 -0
  10. package/dist/{body-Dv9hQ0Qk.mjs → body-DRBgxS6-.mjs} +3 -2
  11. package/dist/{branches-BujtceGr.mjs → branches-C5Jcw8wu.mjs} +8 -6
  12. package/dist/cancel-Ca3r7Y6v.mjs +56 -0
  13. package/dist/{cancel-task-CT2xUMRg.mjs → cancel-task-C1-8vDKS.mjs} +9 -7
  14. package/dist/card-BGAy3eIb.mjs +20 -0
  15. package/dist/{card-CsXk8T6A.mjs → card-CAEZWixN.mjs} +34 -15
  16. package/dist/cards-CILfMPUP.mjs +37 -0
  17. package/dist/cli.mjs +33 -14
  18. package/dist/collection-B3sPXRLs.mjs +163 -0
  19. package/dist/collection-D8cnCB98.mjs +19 -0
  20. package/dist/create-3Z6rm-4O.mjs +44 -0
  21. package/dist/create-BsY5RrVY.mjs +44 -0
  22. package/dist/create-C4OCclBD.mjs +48 -0
  23. package/dist/create-COsD7Vzm.mjs +48 -0
  24. package/dist/create-CP8ou91U.mjs +125 -0
  25. package/dist/create-CeIi_QLj.mjs +66 -0
  26. package/dist/create-CqNw6PmR.mjs +50 -0
  27. package/dist/create-DE_5NrFy.mjs +48 -0
  28. package/dist/{create-B8ektf-R.mjs → create-MEhhhgMC.mjs} +8 -6
  29. package/dist/create-QxDmleKJ.mjs +48 -0
  30. package/dist/{create-branch-goZBTNnr.mjs → create-branch-CKMYaAHk.mjs} +9 -7
  31. package/dist/credentials-CwRKvdP2.mjs +85 -0
  32. package/dist/{current-task-DBjRNCFq.mjs → current-task-Dutjys16.mjs} +9 -7
  33. package/dist/dashboard-B4fVp392.mjs +20 -0
  34. package/dist/dashboard-CnMD04PQ.mjs +163 -0
  35. package/dist/database-BMTb0CzV.mjs +17 -0
  36. package/dist/database-Dvkfy3JM.mjs +51 -0
  37. package/dist/db-ACuuaEok.mjs +22 -0
  38. package/dist/{delete-8vGU35r3.mjs → delete-BMQZuVXZ.mjs} +7 -5
  39. package/dist/{delete-B27KLF5X.mjs → delete-BvcA4jPj.mjs} +7 -5
  40. package/dist/{delete-runtime-Byr60cR3.mjs → delete-runtime-BMzvfj_B.mjs} +4 -4
  41. package/dist/{delete-table-BNaJ_gA4.mjs → delete-table-DUPjHKk4.mjs} +7 -5
  42. package/dist/deprovision-Bsc1S15j.mjs +61 -0
  43. package/dist/{dirty-aNUuph4I.mjs → dirty-CXcdoUhY.mjs} +8 -6
  44. package/dist/docker-D-ieBsP7.mjs +612 -0
  45. package/dist/eid-pvOsEMPZ.mjs +13 -0
  46. package/dist/{export-QDkuuzSE.mjs → export-BjGhLEOi.mjs} +30 -23
  47. package/dist/field-BI2bt8e9.mjs +18 -0
  48. package/dist/field-DciLbuv-.mjs +276 -0
  49. package/dist/fields-Do8HHm_T.mjs +38 -0
  50. package/dist/flag-pair-DtR1AiBQ.mjs +17 -0
  51. package/dist/{get-BGBIzMKY.mjs → get-BGFGWkH0.mjs} +6 -4
  52. package/dist/get-BmE_VHdl.mjs +36 -0
  53. package/dist/{get-DI_IJvgk.mjs → get-C7sshmqF.mjs} +6 -4
  54. package/dist/get-CObKBj2J.mjs +36 -0
  55. package/dist/get-Cq5U_Eep.mjs +40 -0
  56. package/dist/get-D4GUJBiX.mjs +41 -0
  57. package/dist/{get-COXHplHP.mjs → get-DFrsi77F.mjs} +7 -5
  58. package/dist/get-DczxeETg.mjs +53 -0
  59. package/dist/{get-Cl8-IauC.mjs → get-DeQa3ThJ.mjs} +7 -4
  60. package/dist/get-DhZ_dGUb.mjs +36 -0
  61. package/dist/{get-i6LWOByV.mjs → get-DzCVafyO.mjs} +6 -4
  62. package/dist/get-YCnVqq-z.mjs +49 -0
  63. package/dist/get-run-CTyW29s3.mjs +36 -0
  64. package/dist/git-sync-BOmT8HEU.mjs +28 -0
  65. package/dist/{has-remote-changes-hjKoQuRy.mjs → has-remote-changes-xX8vMVsX.mjs} +8 -6
  66. package/dist/{import-HJsSKRYx.mjs → import-CaAUNtXz.mjs} +11 -9
  67. package/dist/{input-Dojr-RTw.mjs → input-ikCiip6x.mjs} +2 -1
  68. package/dist/is-dirty-CPu-xqkW.mjs +10 -0
  69. package/dist/{is-dirty-1Qy7hiHB.mjs → is-dirty-mgxEwEk4.mjs} +5 -4
  70. package/dist/items-Cg67tdto.mjs +77 -0
  71. package/dist/{key-DBxPSFwi.mjs → key-NDEARu2L.mjs} +1 -1
  72. package/dist/{license-MoWse3ZI.mjs → license-CwKzVMD0.mjs} +3 -3
  73. package/dist/list-BqdNQ1nU.mjs +47 -0
  74. package/dist/list-BwGdD45N.mjs +32 -0
  75. package/dist/list-CfOVsAZz.mjs +55 -0
  76. package/dist/list-CpyNn1Zn.mjs +32 -0
  77. package/dist/list-CwwOoGLK.mjs +40 -0
  78. package/dist/{list-C_PRdL5e.mjs → list-DD8CQx8l.mjs} +7 -5
  79. package/dist/{list-Bk6RsbJl.mjs → list-DL-RWpIE.mjs} +5 -3
  80. package/dist/list-DLlq3FyS.mjs +61 -0
  81. package/dist/list-DdQ4jmUQ.mjs +52 -0
  82. package/dist/{list-C4Ajrw8f.mjs → list-DshbLoqR.mjs} +6 -3
  83. package/dist/{list-C8tdLOH5.mjs → list-DzTMpoBs.mjs} +5 -3
  84. package/dist/list-JgRtCzz3.mjs +32 -0
  85. package/dist/{list-CWt3fqrZ.mjs → list-WzgJcwB5.mjs} +5 -3
  86. package/dist/{login-C9WTwNn6.mjs → login-DJnmR2wX.mjs} +14 -5
  87. package/dist/{logout-oLszGCOg.mjs → logout-BMe_1Zp8.mjs} +7 -6
  88. package/dist/logs-CQxKJ3HG.mjs +58 -0
  89. package/dist/{manifest-CAdjQYH8.mjs → manifest-Dv5B9Blc.mjs} +3 -7
  90. package/dist/measure-BEQfnLdN.mjs +67 -0
  91. package/dist/measure-BGyYbtqO.mjs +19 -0
  92. package/dist/metadata-CLIALntn.mjs +37 -0
  93. package/dist/metadata-T-fNUWg_.mjs +38 -0
  94. package/dist/{package-BGfw4ZWJ.mjs → package-DBsS7a5x.mjs} +7 -1
  95. package/dist/paginate-CTSfuYiF.mjs +49 -0
  96. package/dist/parse-id-BUOZQqjp.mjs +12 -0
  97. package/dist/parse-ref-DGvh4aDn.mjs +17 -0
  98. package/dist/parse-schemas-BnW4T1_I.mjs +12 -0
  99. package/dist/{poll-ILanYysl.mjs → poll-DMmmZWvi.mjs} +2 -1
  100. package/dist/{poll-task-DbpsiQhl.mjs → poll-task-2Ckiwp8U.mjs} +8 -7
  101. package/dist/predicates-DiIiS3k7.mjs +153 -0
  102. package/dist/preflight-CC_g6EWU.mjs +91 -0
  103. package/dist/{prompt-DpT8yAVy.mjs → prompt-Bf3DQ-qE.mjs} +1 -1
  104. package/dist/provision-BUgWJWAV.mjs +77 -0
  105. package/dist/ps-BUNHygf-.mjs +10 -0
  106. package/dist/ps-Yv0JjLVN.mjs +78 -0
  107. package/dist/{query-PihYi-UZ.mjs → query-CzfbuG8a.mjs} +38 -13
  108. package/dist/query-UIebHmbT.mjs +90 -0
  109. package/dist/remove-BAUbcwuF.mjs +98 -0
  110. package/dist/{remove-B2hVYn1v.mjs → remove-CN2PNGTR.mjs} +6 -5
  111. package/dist/remove-collection-C6NxEh53.mjs +38 -0
  112. package/dist/render-DXv-D6fU.mjs +182 -0
  113. package/dist/rescan-values-CcB4F9qa.mjs +43 -0
  114. package/dist/revision-message-flag-CWQbKhdl.mjs +11 -0
  115. package/dist/{run-C2so6Qp6.mjs → run-BjXZtu_6.mjs} +27 -36
  116. package/dist/runs-CXx7l1NY.mjs +54 -0
  117. package/dist/{runtime-C9CEZhcn.mjs → runtime-D7jihh81.mjs} +425 -442
  118. package/dist/schema-tables-BCJT2DM_.mjs +45 -0
  119. package/dist/schemas-DlNpbn4H.mjs +47 -0
  120. package/dist/{search-CopOytXY.mjs → search-Dt-6mdHZ.mjs} +6 -19
  121. package/dist/segment-BMrUBz94.mjs +70 -0
  122. package/dist/segment-C52QNnSs.mjs +19 -0
  123. package/dist/{set-BcF7M1GQ.mjs → set-DCESWpi3.mjs} +6 -4
  124. package/dist/{set-CbibegpA.mjs → set-L7cuHjVZ.mjs} +8 -6
  125. package/dist/{setting-U3NtBMFo.mjs → setting-DysGAuYS.mjs} +3 -3
  126. package/dist/setup-_ypJDPAY.mjs +71 -0
  127. package/dist/snippet-Dw0Sjzkr.mjs +64 -0
  128. package/dist/snippet-vb3G9R8a.mjs +19 -0
  129. package/dist/start-BokXnb0V.mjs +350 -0
  130. package/dist/{stash-DOBbYozC.mjs → stash-CaGX6PfX.mjs} +9 -7
  131. package/dist/{status-Buf1ZbNR.mjs → status-BaX9vedb.mjs} +10 -8
  132. package/dist/{status-CUcs8XBH.mjs → status-CyecXzN4.mjs} +4 -2
  133. package/dist/{status-D1F5XHae.mjs → status-RpVyPEty.mjs} +4 -2
  134. package/dist/stop-BRuF_Cg1.mjs +81 -0
  135. package/dist/summary-CpEOiOlZ.mjs +41 -0
  136. package/dist/sync-schema-4Cl4h8Jn.mjs +43 -0
  137. package/dist/table-BeMWuvzO.mjs +19 -0
  138. package/dist/{table-Cfk7oSvw.mjs → table-jljEqZ0R.mjs} +22 -9
  139. package/dist/transform-DwRc-w6y.mjs +24 -0
  140. package/dist/{transform-B5uRpg1G.mjs → transform-IEX4Mx3X.mjs} +56 -2
  141. package/dist/transform-job-BigWrctt.mjs +19 -0
  142. package/dist/{transform-job-C7QXWTVE.mjs → transform-job-Csr86muI.mjs} +7 -0
  143. package/dist/translate-DqLlXXUx.mjs +111 -0
  144. package/dist/tree-BT24nkLM.mjs +32 -0
  145. package/dist/update-BCXKQi2n.mjs +52 -0
  146. package/dist/{update-CL8tRbxr.mjs → update-BXbLmC2b.mjs} +9 -7
  147. package/dist/update-C1Frz9GR.mjs +52 -0
  148. package/dist/update-C5goGhNr.mjs +56 -0
  149. package/dist/update-CCOyB0iT.mjs +73 -0
  150. package/dist/update-D04NMueX.mjs +59 -0
  151. package/dist/update-D6WVtNV1.mjs +57 -0
  152. package/dist/update-DFR46LsB.mjs +56 -0
  153. package/dist/update-DyLItrpV.mjs +56 -0
  154. package/dist/update-dashcard-av0_PYeg.mjs +71 -0
  155. package/dist/update-mrgvQF4i.mjs +51 -0
  156. package/dist/url-x4wn_l3k.mjs +54 -0
  157. package/dist/uuid-BZHbti8B.mjs +47 -0
  158. package/dist/validate-DCYx6jdL.mjs +1496 -0
  159. package/dist/validate-query-B07oGG4K.mjs +37 -0
  160. package/dist/values-Be6i0Fs9.mjs +36 -0
  161. package/dist/{wait-Bugr9eXD.mjs → wait-BMqQD8k_.mjs} +10 -8
  162. package/dist/wait-CWizX_sR.mjs +19 -0
  163. package/dist/wait-flags-DO3ar2tf.mjs +35 -0
  164. package/dist/workspace-CG1xyJ86.mjs +24 -0
  165. package/dist/workspace-DVuqKJGG.mjs +72 -0
  166. package/dist/workspace-credentials-B6BL-X0d.mjs +139 -0
  167. package/package.json +7 -1
  168. package/dist/auth-BF7IjZIH.mjs +0 -18
  169. package/dist/card-_Ta7zdYe.mjs +0 -19
  170. package/dist/create-CI2Cunq5.mjs +0 -38
  171. package/dist/create-DdbU3TLX.mjs +0 -42
  172. package/dist/database-PA9Goi25.mjs +0 -33
  173. package/dist/db-DMghzgb6.mjs +0 -17
  174. package/dist/field-C8IVs6rp.mjs +0 -76
  175. package/dist/field-DaYo_90x.mjs +0 -13
  176. package/dist/get-Cwpj7lDe.mjs +0 -35
  177. package/dist/get-Dh_acl8q.mjs +0 -34
  178. package/dist/is-dirty-DpKn9HJp.mjs +0 -8
  179. package/dist/list-CBSBHtK-.mjs +0 -38
  180. package/dist/parse-id-BhmmfyCP.mjs +0 -14
  181. package/dist/sync-BPyGXfUk.mjs +0 -26
  182. package/dist/table-D7nJt7JO.mjs +0 -16
  183. package/dist/transform-UbyewMxY.mjs +0 -21
  184. package/dist/transform-job-CrYkr-Ma.mjs +0 -19
  185. package/dist/update-DU2oU2j-.mjs +0 -49
  186. /package/dist/{body-flags-BUA9XV1u.mjs → body-flags-BK7J6Daz.mjs} +0 -0
  187. /package/dist/{setting-26ckqHAP.mjs → setting-CTaAeMci.mjs} +0 -0
@@ -0,0 +1,153 @@
1
+ import { ZodError, core } from "zod";
2
+ import { isCancel } from "@clack/prompts";
3
+
4
+ //#region src/core/json-pointer.ts
5
+ function escapeJsonPointerSegment(key) {
6
+ if (typeof key === "number") return String(key);
7
+ const segment = typeof key === "symbol" ? key.toString() : key;
8
+ return segment.replaceAll("~", "~0").replaceAll("/", "~1");
9
+ }
10
+
11
+ //#endregion
12
+ //#region src/core/errors.ts
13
+ const VERBOSE_ENV = "METABASE_VERBOSE";
14
+ var MetabaseError = class extends Error {
15
+ get userMessage() {
16
+ return this.message;
17
+ }
18
+ };
19
+ var NetworkError = class extends MetabaseError {
20
+ category = "network";
21
+ isRetryable = true;
22
+ exitCode = 1;
23
+ developerDetail;
24
+ constructor(message, developerDetail) {
25
+ super(message);
26
+ this.name = "NetworkError";
27
+ this.developerDetail = developerDetail;
28
+ }
29
+ };
30
+ var TimeoutError = class extends MetabaseError {
31
+ category = "timeout";
32
+ isRetryable = true;
33
+ exitCode = 1;
34
+ developerDetail;
35
+ constructor(message, developerDetail) {
36
+ super(message);
37
+ this.name = "TimeoutError";
38
+ this.developerDetail = developerDetail;
39
+ }
40
+ };
41
+ var ValidationError = class extends MetabaseError {
42
+ category = "validation";
43
+ isRetryable = false;
44
+ exitCode = 1;
45
+ developerDetail;
46
+ constructor(message, developerDetail) {
47
+ super(message);
48
+ this.name = "ValidationError";
49
+ this.developerDetail = developerDetail;
50
+ }
51
+ get userMessage() {
52
+ const issues = this.developerDetail.zodIssues;
53
+ if (issues.length === 0) return this.message;
54
+ return `${this.message}\n${formatZodIssueList(issues)}`;
55
+ }
56
+ };
57
+ const MAX_ISSUES_PRINTED = 10;
58
+ function formatZodIssueList(issues) {
59
+ const head = issues.slice(0, MAX_ISSUES_PRINTED).map(formatZodIssueLine);
60
+ const overflow = issues.length - MAX_ISSUES_PRINTED;
61
+ if (overflow > 0) head.push(` ... and ${overflow} more`);
62
+ return head.join("\n");
63
+ }
64
+ function formatZodIssueLine(issue) {
65
+ return ` ${formatZodIssuePointer(issue.path)}: ${issue.message}`;
66
+ }
67
+ function formatZodIssuePointer(path) {
68
+ if (path.length === 0) return "/";
69
+ return path.map((key) => `/${escapeJsonPointerSegment(key)}`).join("");
70
+ }
71
+ var ConfigError = class extends MetabaseError {
72
+ category = "config";
73
+ isRetryable = false;
74
+ exitCode = 2;
75
+ developerDetail = null;
76
+ constructor(message) {
77
+ super(message);
78
+ this.name = "ConfigError";
79
+ }
80
+ };
81
+ var AbortError = class extends MetabaseError {
82
+ category = "abort";
83
+ isRetryable = false;
84
+ exitCode = 130;
85
+ developerDetail = null;
86
+ constructor(message = "aborted") {
87
+ super(message);
88
+ this.name = "AbortError";
89
+ }
90
+ };
91
+ var ChainedRequestError = class extends MetabaseError {
92
+ cause;
93
+ constructor(message, cause) {
94
+ super(message);
95
+ this.name = "ChainedRequestError";
96
+ this.cause = cause;
97
+ }
98
+ get category() {
99
+ return this.cause.category;
100
+ }
101
+ get isRetryable() {
102
+ return this.cause.isRetryable;
103
+ }
104
+ get exitCode() {
105
+ return this.cause.exitCode;
106
+ }
107
+ get developerDetail() {
108
+ return this.cause.developerDetail;
109
+ }
110
+ };
111
+ var UnknownError = class extends MetabaseError {
112
+ category = "unknown";
113
+ isRetryable = false;
114
+ exitCode = 1;
115
+ developerDetail;
116
+ constructor(input) {
117
+ super(input.originalMessage);
118
+ this.name = "UnknownError";
119
+ this.developerDetail = input;
120
+ }
121
+ };
122
+ function toMetabaseError(error) {
123
+ if (error instanceof MetabaseError) return error;
124
+ if (isCancel(error)) return new AbortError();
125
+ if (error instanceof ZodError) return new ConfigError(error.issues.map(formatZodIssue).join("; "));
126
+ if (error instanceof Error) return new UnknownError({
127
+ originalMessage: error.message,
128
+ stack: error.stack ?? null
129
+ });
130
+ return new UnknownError({
131
+ originalMessage: String(error),
132
+ stack: null
133
+ });
134
+ }
135
+ function formatZodIssue(issue) {
136
+ const path = core.toDotPath(issue.path);
137
+ return path === "" ? issue.message : `${path}: ${issue.message}`;
138
+ }
139
+ function isNotFoundError(value) {
140
+ return value instanceof Error && "code" in value && value.code === "ENOENT";
141
+ }
142
+ function errorMessage(value) {
143
+ return value instanceof Error ? value.message : String(value);
144
+ }
145
+
146
+ //#endregion
147
+ //#region src/runtime/predicates.ts
148
+ function isPlainObject(value) {
149
+ return typeof value === "object" && value !== null && !Array.isArray(value);
150
+ }
151
+
152
+ //#endregion
153
+ export { AbortError, ChainedRequestError, ConfigError, MetabaseError, NetworkError, TimeoutError, VERBOSE_ENV, ValidationError, errorMessage, escapeJsonPointerSegment, isNotFoundError, isPlainObject, toMetabaseError };
@@ -0,0 +1,91 @@
1
+ import { writeJson } from "./render-DXv-D6fU.mjs";
2
+ import { ChainedRequestError, ConfigError, MetabaseError } from "./predicates-DiIiS3k7.mjs";
3
+ import { HttpError } from "./runtime-D7jihh81.mjs";
4
+ import { Card } from "./card-CAEZWixN.mjs";
5
+ import { z } from "zod";
6
+
7
+ //#region src/commands/dashboard/preflight.ts
8
+ const PreflightDashcard = z.looseObject({ card_id: z.number().int().nullable().optional() });
9
+ function collectDashcardCardReferences(dashcards) {
10
+ if (dashcards === void 0) return [];
11
+ const refs = [];
12
+ dashcards.forEach((dashcard, index) => {
13
+ const parsed = PreflightDashcard.safeParse(dashcard);
14
+ if (!parsed.success) return;
15
+ const cardId = parsed.data.card_id;
16
+ if (typeof cardId === "number" && cardId > 0) refs.push({
17
+ cardId,
18
+ path: `/dashcards/${index}/card_id`
19
+ });
20
+ });
21
+ return refs;
22
+ }
23
+ async function preflightDashcardCardReferences(client, dashcards) {
24
+ const references = collectDashcardCardReferences(dashcards);
25
+ if (references.length === 0) return;
26
+ const grouped = new Map();
27
+ for (const ref of references) {
28
+ const list = grouped.get(ref.cardId);
29
+ if (list === void 0) grouped.set(ref.cardId, [ref]);
30
+ else list.push(ref);
31
+ }
32
+ const checks = await Promise.all(Array.from(grouped.entries()).map(async ([cardId, refs]) => ({
33
+ refs,
34
+ result: await classifyCardReference(client, cardId)
35
+ })));
36
+ const errors = [];
37
+ for (const check of checks) {
38
+ if (check.result.status === "ok") continue;
39
+ for (const ref of check.refs) errors.push({
40
+ path: ref.path,
41
+ message: check.result.message
42
+ });
43
+ }
44
+ if (errors.length === 0) return;
45
+ const outcome = {
46
+ ok: false,
47
+ errors
48
+ };
49
+ writeJson(outcome);
50
+ throw new ConfigError(`dashboard card-reference pre-flight failed: ${errors.length} error(s) — fix the dashcard card_id values listed above`);
51
+ }
52
+ function wrapChainedDashboardWriteError(error, dashboardId) {
53
+ if (!(error instanceof MetabaseError)) return error;
54
+ const prefix = `dashboard ${dashboardId} created but follow-up PUT /api/dashboard/${dashboardId} failed`;
55
+ const suffix = "dashcards not applied";
56
+ const message = `${prefix}: ${error.userMessage}; ${suffix}`;
57
+ if (error instanceof HttpError) return new HttpError({
58
+ status: error.status,
59
+ statusText: error.developerDetail.statusText,
60
+ method: error.developerDetail.method,
61
+ url: error.developerDetail.url,
62
+ responseHeaders: error.developerDetail.responseHeaders,
63
+ rawBody: error.developerDetail.body,
64
+ overrideUserMessage: message
65
+ });
66
+ return new ChainedRequestError(message, error);
67
+ }
68
+ async function classifyCardReference(client, cardId) {
69
+ try {
70
+ const card = await client.requestParsed(Card, `/api/card/${cardId}`);
71
+ if (card.archived) return {
72
+ status: "error",
73
+ message: `card ${cardId} is archived`
74
+ };
75
+ return { status: "ok" };
76
+ } catch (error) {
77
+ if (!(error instanceof HttpError)) throw error;
78
+ if (error.status === 404) return {
79
+ status: "error",
80
+ message: `card ${cardId} not found`
81
+ };
82
+ if (error.status === 401 || error.status === 403) return {
83
+ status: "error",
84
+ message: `card ${cardId} is not readable: ${error.userMessage}`
85
+ };
86
+ throw error;
87
+ }
88
+ }
89
+
90
+ //#endregion
91
+ export { preflightDashcardCardReferences, wrapChainedDashboardWriteError };
@@ -1,4 +1,4 @@
1
- import { AbortError, ConfigError } from "./runtime-C9CEZhcn.mjs";
1
+ import { AbortError, ConfigError } from "./predicates-DiIiS3k7.mjs";
2
2
  import { confirm, isCancel, password, text } from "@clack/prompts";
3
3
 
4
4
  //#region src/output/prompt.ts
@@ -0,0 +1,77 @@
1
+ import "./package-DBsS7a5x.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderItem } from "./render-DXv-D6fU.mjs";
4
+ import { ConfigError } from "./predicates-DiIiS3k7.mjs";
5
+ import "./input-ikCiip6x.mjs";
6
+ import { connectionFlags, defineMetabaseCommand, outputFlags, profileFlag } from "./runtime-D7jihh81.mjs";
7
+ import { readBody } from "./body-DRBgxS6-.mjs";
8
+ import { bodyInputFlags } from "./body-flags-BK7J6Daz.mjs";
9
+ import { parseId } from "./parse-id-BUOZQqjp.mjs";
10
+ import "./poll-DMmmZWvi.mjs";
11
+ import { parseWaitFlags, waitFlags } from "./wait-flags-DO3ar2tf.mjs";
12
+ import { Workspace, WorkspaceProvisionInput, workspaceView } from "./workspace-DVuqKJGG.mjs";
13
+ import { waitForDatabaseProvisioned } from "./wait-CWizX_sR.mjs";
14
+ import { parseSchemasCsv } from "./parse-schemas-BnW4T1_I.mjs";
15
+
16
+ //#region src/commands/workspace/database/provision.ts
17
+ var provision_default = defineMetabaseCommand({
18
+ meta: {
19
+ name: "provision",
20
+ description: "Provision a database into a workspace"
21
+ },
22
+ args: {
23
+ ...outputFlags,
24
+ ...profileFlag,
25
+ ...connectionFlags,
26
+ ...bodyInputFlags,
27
+ ...waitFlags,
28
+ "database-id": {
29
+ type: "string",
30
+ description: "Database id (alternative to --body / --file)"
31
+ },
32
+ schemas: {
33
+ type: "string",
34
+ description: "Comma-separated input schemas (alternative to --body / --file)"
35
+ },
36
+ id: {
37
+ type: "positional",
38
+ description: "Workspace id",
39
+ required: true
40
+ }
41
+ },
42
+ outputSchema: Workspace,
43
+ examples: [
44
+ "metabase workspace database provision 1 --database-id 5 --schemas analytics,github",
45
+ "metabase workspace database provision 1 --database-id 5 --schemas analytics --wait",
46
+ "metabase workspace database provision 1 --file provision.json"
47
+ ],
48
+ async run({ args, ctx, getClient }) {
49
+ const workspaceId = parseId(args.id);
50
+ const databaseIdFlag = args["database-id"];
51
+ const schemasFlag = args.schemas;
52
+ const wait = parseWaitFlags(args);
53
+ let body;
54
+ if (databaseIdFlag !== void 0 && databaseIdFlag !== "") {
55
+ const databaseId = parseId(databaseIdFlag, "--database-id");
56
+ if (schemasFlag === void 0 || schemasFlag === "") throw new ConfigError("--schemas is required when using --database-id");
57
+ const input_schemas = parseSchemasCsv(schemasFlag);
58
+ body = WorkspaceProvisionInput.parse({
59
+ database_id: databaseId,
60
+ input_schemas
61
+ });
62
+ } else body = await readBody({
63
+ flag: args.body,
64
+ file: args.file
65
+ }, WorkspaceProvisionInput);
66
+ const client = await getClient();
67
+ const initial = await client.requestParsed(Workspace, `/api/ee/workspace-manager/${workspaceId}/database`, {
68
+ method: "POST",
69
+ body
70
+ });
71
+ const final = wait.enabled ? await waitForDatabaseProvisioned(client, workspaceId, body.database_id, wait.schedule) : initial;
72
+ renderItem(final, workspaceView, ctx);
73
+ }
74
+ });
75
+
76
+ //#endregion
77
+ export { provision_default as default };
@@ -0,0 +1,10 @@
1
+ import "./package-DBsS7a5x.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import "./render-DXv-D6fU.mjs";
4
+ import "./predicates-DiIiS3k7.mjs";
5
+ import "./runtime-D7jihh81.mjs";
6
+ import "./poll-DMmmZWvi.mjs";
7
+ import "./docker-D-ieBsP7.mjs";
8
+ import { LocalWorkspace, LocalWorkspaceCompact, LocalWorkspaceListEnvelope, LocalWorkspaceState, localWorkspaceView, ps_default } from "./ps-Yv0JjLVN.mjs";
9
+
10
+ export { ps_default as default };
@@ -0,0 +1,78 @@
1
+ import { renderList } from "./render-DXv-D6fU.mjs";
2
+ import { defineMetabaseCommand, listEnvelopeSchema, localUrl, outputFlags, wrapList } from "./runtime-D7jihh81.mjs";
3
+ import { CONTAINER_STATES, checkDockerReady, listWorkspaceContainers } from "./docker-D-ieBsP7.mjs";
4
+ import { z } from "zod";
5
+
6
+ //#region src/commands/workspace/ps.ts
7
+ const LocalWorkspaceState = z.enum(CONTAINER_STATES);
8
+ const LocalWorkspace = z.object({
9
+ workspace_id: z.number().int().positive(),
10
+ workspace_name: z.string(),
11
+ container_name: z.string(),
12
+ state: LocalWorkspaceState,
13
+ status: z.string(),
14
+ image: z.string(),
15
+ profile: z.string().nullable(),
16
+ parent_url: z.string().nullable(),
17
+ host_port: z.number().int().positive().nullable(),
18
+ url: z.string().nullable()
19
+ });
20
+ const LocalWorkspaceCompact = LocalWorkspace.pick({
21
+ workspace_id: true,
22
+ workspace_name: true,
23
+ state: true,
24
+ url: true
25
+ }).strip();
26
+ const localWorkspaceView = {
27
+ compactPick: LocalWorkspaceCompact,
28
+ tableColumns: [
29
+ {
30
+ key: "workspace_id",
31
+ label: "ID"
32
+ },
33
+ {
34
+ key: "workspace_name",
35
+ label: "Name"
36
+ },
37
+ {
38
+ key: "state",
39
+ label: "State"
40
+ },
41
+ {
42
+ key: "url",
43
+ label: "URL",
44
+ format: (value) => typeof value === "string" ? value : "—"
45
+ }
46
+ ]
47
+ };
48
+ const LocalWorkspaceListEnvelope = listEnvelopeSchema(LocalWorkspaceCompact);
49
+ var ps_default = defineMetabaseCommand({
50
+ meta: {
51
+ name: "ps",
52
+ description: "List workspaces with a local container (running or stopped)"
53
+ },
54
+ args: { ...outputFlags },
55
+ outputSchema: LocalWorkspaceListEnvelope,
56
+ examples: ["metabase workspace ps", "metabase workspace ps --json"],
57
+ async run({ ctx }) {
58
+ await checkDockerReady();
59
+ const summaries = await listWorkspaceContainers();
60
+ const items = summaries.map((summary) => ({
61
+ workspace_id: summary.workspaceId,
62
+ workspace_name: summary.workspaceName,
63
+ container_name: summary.name,
64
+ state: summary.state,
65
+ status: summary.status,
66
+ image: summary.image,
67
+ profile: summary.profile,
68
+ parent_url: summary.parentUrl,
69
+ host_port: summary.hostPort,
70
+ url: summary.hostPort !== null && summary.state === "running" ? localUrl(summary.hostPort) : null
71
+ }));
72
+ items.sort((a, b) => a.workspace_id - b.workspace_id);
73
+ renderList(wrapList(items), localWorkspaceView, ctx);
74
+ }
75
+ });
76
+
77
+ //#endregion
78
+ export { LocalWorkspace, LocalWorkspaceCompact, LocalWorkspaceListEnvelope, LocalWorkspaceState, localWorkspaceView, ps_default };
@@ -1,8 +1,11 @@
1
- import "./package-BGfw4ZWJ.mjs";
1
+ import "./package-DBsS7a5x.mjs";
2
2
  import "./command-augment-D9pI9Vbh.mjs";
3
- import { ConfigError, connectionFlags, defineMetabaseCommand, outputFlags, parseJson, profileFlag, renderItem } from "./runtime-C9CEZhcn.mjs";
4
- import { CardQueryResult, cardQueryView } from "./card-CsXk8T6A.mjs";
5
- import { parseId } from "./parse-id-BhmmfyCP.mjs";
3
+ import { renderItem } from "./render-DXv-D6fU.mjs";
4
+ import { ConfigError } from "./predicates-DiIiS3k7.mjs";
5
+ import { connectionFlags, defineMetabaseCommand, outputFlags, parseJson, profileFlag } from "./runtime-D7jihh81.mjs";
6
+ import { parseId } from "./parse-id-BUOZQqjp.mjs";
7
+ import "./field-DciLbuv-.mjs";
8
+ import { CardQueryResult, cardQueryView } from "./card-CAEZWixN.mjs";
6
9
  import { z } from "zod";
7
10
  import { Writable } from "node:stream";
8
11
 
@@ -13,12 +16,16 @@ async function pipeToStdout(stream) {
13
16
 
14
17
  //#endregion
15
18
  //#region src/commands/card/query.ts
16
- const ExportFormat = z.enum(["csv", "xlsx"]);
19
+ const ExportFormat = z.enum([
20
+ "csv",
21
+ "json",
22
+ "xlsx"
23
+ ]);
17
24
  const QueryParameters = z.array(z.unknown());
18
25
  var query_default = defineMetabaseCommand({
19
26
  meta: {
20
27
  name: "query",
21
- description: "Run a saved card and return results (json envelope, CSV, or XLSX)"
28
+ description: "Run a saved card and return results (json envelope, or stream CSV/JSON/XLSX via --export-format)"
22
29
  },
23
30
  args: {
24
31
  ...outputFlags,
@@ -39,7 +46,17 @@ var query_default = defineMetabaseCommand({
39
46
  },
40
47
  limit: {
41
48
  type: "string",
42
- description: "Cap rows kept in the JSON envelope (no effect on csv/xlsx exports)"
49
+ description: "Cap rows kept in the JSON envelope (no effect on streamed exports)"
50
+ },
51
+ "format-rows": {
52
+ type: "boolean",
53
+ description: "Streamed exports only: apply visualization-settings formatting to values (default false)",
54
+ default: false
55
+ },
56
+ "pivot-results": {
57
+ type: "boolean",
58
+ description: "Streamed exports only: emit the pivoted output for pivot questions (default false)",
59
+ default: false
43
60
  }
44
61
  },
45
62
  outputSchema: CardQueryResult,
@@ -55,8 +72,12 @@ var query_default = defineMetabaseCommand({
55
72
  const client = await getClient();
56
73
  const exportFormatRaw = args["export-format"];
57
74
  if (exportFormatRaw !== void 0 && exportFormatRaw !== "") {
58
- const exportFormat = parseExportFormat(exportFormatRaw);
59
- await streamExport(client, id, exportFormat, parameters);
75
+ await streamExport(client, id, {
76
+ format: parseExportFormat(exportFormatRaw),
77
+ parameters,
78
+ formatRows: args["format-rows"],
79
+ pivotResults: args["pivot-results"]
80
+ });
60
81
  return;
61
82
  }
62
83
  const result = await client.requestParsed(CardQueryResult, `/api/card/${id}/query`, {
@@ -77,7 +98,7 @@ function parseExportFormat(raw) {
77
98
  return result.data;
78
99
  }
79
100
  function applyLimit(result, limit) {
80
- if (limit === null || result.status !== "completed" || result.data.rows.length <= limit) return result;
101
+ if (limit === null || result.data === void 0 || result.data.rows.length <= limit) return result;
81
102
  return {
82
103
  ...result,
83
104
  data: {
@@ -86,9 +107,13 @@ function applyLimit(result, limit) {
86
107
  }
87
108
  };
88
109
  }
89
- async function streamExport(client, id, format, parameters) {
90
- const body = new URLSearchParams({ parameters: JSON.stringify(parameters) });
91
- const stream = await client.requestStream(`/api/card/${id}/query/${format}`, {
110
+ async function streamExport(client, id, options) {
111
+ const body = new URLSearchParams({
112
+ parameters: JSON.stringify(options.parameters),
113
+ format_rows: String(options.formatRows),
114
+ pivot_results: String(options.pivotResults)
115
+ });
116
+ const stream = await client.requestStream(`/api/card/${id}/query/${options.format}`, {
92
117
  method: "POST",
93
118
  body
94
119
  });
@@ -0,0 +1,90 @@
1
+ import "./package-DBsS7a5x.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderItem, writeJson } from "./render-DXv-D6fU.mjs";
4
+ import { ConfigError } from "./predicates-DiIiS3k7.mjs";
5
+ import "./input-ikCiip6x.mjs";
6
+ import { connectionFlags, defineMetabaseCommand, outputFlags, profileFlag } from "./runtime-D7jihh81.mjs";
7
+ import { readBody } from "./body-DRBgxS6-.mjs";
8
+ import { bodyInputFlags } from "./body-flags-BK7J6Daz.mjs";
9
+ import "./field-DciLbuv-.mjs";
10
+ import { CardQueryResult, cardQueryView } from "./card-CAEZWixN.mjs";
11
+ import { assertNotLegacyEnvelopeWrappingMbql5, getQuerySchemaBundle, isMbql5Query, validateQuery } from "./validate-DCYx6jdL.mjs";
12
+ import { skipValidateFlag } from "./validate-query-B07oGG4K.mjs";
13
+ import { z } from "zod";
14
+
15
+ //#region src/commands/query.ts
16
+ const QueryBody = z.unknown();
17
+ const QUERY_ENDPOINT = "/api/dataset";
18
+ var query_default = defineMetabaseCommand({
19
+ meta: {
20
+ name: "query",
21
+ description: "Run an MBQL 5 query (validates against the bundled schema first); --print-schema emits the schema for agent discovery, --dry-run validates without sending. Any non-MBQL 5 body — legacy MBQL 4 ({type:\"query\", …}), legacy native ({type:\"native\", …}), or any other non-{lib/type:\"mbql/query\"} shape — skips pre-flight automatically and is normalized server-side by lib-be/normalize-query. The bundled schema only models MBQL 5. Every clause options object carries a `lib/uuid` (UUID v4); mint these via `metabase uuid` — never author them by hand."
22
+ },
23
+ args: {
24
+ ...outputFlags,
25
+ ...profileFlag,
26
+ ...connectionFlags,
27
+ ...bodyInputFlags,
28
+ "dry-run": {
29
+ type: "boolean",
30
+ description: "Validate the body and exit without sending the query"
31
+ },
32
+ "print-schema": {
33
+ type: "boolean",
34
+ description: "Emit the bundled MBQL 5 query JSON Schema and exit; no body required"
35
+ },
36
+ ...skipValidateFlag
37
+ },
38
+ outputSchema: CardQueryResult,
39
+ examples: [
40
+ "metabase query --print-schema",
41
+ "cat q.json | metabase query --dry-run",
42
+ "metabase query --file q.json",
43
+ "metabase query --file q.json --skip-validate"
44
+ ],
45
+ async run({ args, ctx, getClient }) {
46
+ if (args["print-schema"] === true) {
47
+ writeJson(getQuerySchemaBundle());
48
+ return;
49
+ }
50
+ const dryRun = args["dry-run"] === true;
51
+ const explicitSkip = args["skip-validate"] === true;
52
+ if (dryRun && explicitSkip) throw new ConfigError("--skip-validate cannot be combined with --dry-run");
53
+ const body = await readBody({
54
+ flag: args.body,
55
+ file: args.file
56
+ }, QueryBody);
57
+ if (!explicitSkip) assertNotLegacyEnvelopeWrappingMbql5(body, {
58
+ contextLabel: "query",
59
+ bodyNoun: "the body"
60
+ });
61
+ const skipValidation = explicitSkip || !isMbql5Query(body);
62
+ if (!skipValidation) {
63
+ const outcome = validateQuery(body);
64
+ if (!outcome.ok) {
65
+ writeJson(outcome);
66
+ const hint = dryRun ? "" : " — pass --dry-run to validate without sending";
67
+ throw new ConfigError(`validation failed: ${outcome.errors.length} error(s)${hint}`);
68
+ }
69
+ if (dryRun) {
70
+ writeJson(outcome);
71
+ return;
72
+ }
73
+ } else if (dryRun) {
74
+ writeJson({
75
+ ok: true,
76
+ errors: []
77
+ });
78
+ return;
79
+ }
80
+ const client = await getClient();
81
+ const queryResult = await client.requestParsed(CardQueryResult, QUERY_ENDPOINT, {
82
+ method: "POST",
83
+ body
84
+ });
85
+ renderItem(queryResult, cardQueryView, ctx);
86
+ }
87
+ });
88
+
89
+ //#endregion
90
+ export { query_default as default };