@metabase/cli 0.1.0 → 0.1.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 (187) hide show
  1. package/README.md +972 -57
  2. package/dist/add-collection-DwxQDXzL.mjs +54 -0
  3. package/dist/add-collection-SL08iMub.mjs +11 -0
  4. package/dist/api-key-BktzvPb7.mjs +13 -0
  5. package/dist/{archive-CsWeHXle.mjs → archive-C1mF-9Kj.mjs} +7 -4
  6. package/dist/archive-CLWtbvvH.mjs +44 -0
  7. package/dist/archive-Cq4WKmJt.mjs +44 -0
  8. package/dist/archive-kYoy5LK5.mjs +39 -0
  9. package/dist/auth-DfYkakP3.mjs +19 -0
  10. package/dist/{body-Dv9hQ0Qk.mjs → body-rDrR-C1c.mjs} +3 -2
  11. package/dist/{branches-BujtceGr.mjs → branches-CH2UcCpX.mjs} +8 -6
  12. package/dist/cancel-CgLZcItQ.mjs +56 -0
  13. package/dist/{cancel-task-CT2xUMRg.mjs → cancel-task-DcYrFsM6.mjs} +9 -7
  14. package/dist/{card-CsXk8T6A.mjs → card-CQxvHeyP.mjs} +34 -15
  15. package/dist/card-ZCGU2JEh.mjs +20 -0
  16. package/dist/cards-C4NIaERo.mjs +37 -0
  17. package/dist/cli.mjs +33 -14
  18. package/dist/collection-B3sPXRLs.mjs +163 -0
  19. package/dist/collection-D_uFLIAS.mjs +19 -0
  20. package/dist/create-BUCLNqiN.mjs +48 -0
  21. package/dist/create-CB0Yp__0.mjs +66 -0
  22. package/dist/create-CNvd5T8h.mjs +48 -0
  23. package/dist/create-Cbh1cGj9.mjs +48 -0
  24. package/dist/create-CzfNOhOF.mjs +48 -0
  25. package/dist/create-DU0ZhnZu.mjs +44 -0
  26. package/dist/create-Dh0p-c2Y.mjs +44 -0
  27. package/dist/create-DvrVZ2hS.mjs +125 -0
  28. package/dist/create-QgN369N5.mjs +50 -0
  29. package/dist/{create-B8ektf-R.mjs → create-bqc_rmix.mjs} +8 -6
  30. package/dist/{create-branch-goZBTNnr.mjs → create-branch-BJFH9Hda.mjs} +9 -7
  31. package/dist/credentials-DTP1xuKz.mjs +85 -0
  32. package/dist/{current-task-DBjRNCFq.mjs → current-task-z_TiJ0kt.mjs} +9 -7
  33. package/dist/dashboard-CnMD04PQ.mjs +163 -0
  34. package/dist/dashboard-G1-dGLUR.mjs +20 -0
  35. package/dist/database-DQkUxTLd.mjs +17 -0
  36. package/dist/database-vvig8k4x.mjs +51 -0
  37. package/dist/db-CBaEfumR.mjs +22 -0
  38. package/dist/{delete-8vGU35r3.mjs → delete-CVYII8mq.mjs} +7 -5
  39. package/dist/{delete-B27KLF5X.mjs → delete-DeZQ1r9w.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-ZiR9-ndv.mjs} +7 -5
  42. package/dist/deprovision-BhD3J-Am.mjs +61 -0
  43. package/dist/{dirty-aNUuph4I.mjs → dirty-D9agt7Os.mjs} +8 -6
  44. package/dist/docker-CHpV8PRz.mjs +612 -0
  45. package/dist/eid-B5wawMmO.mjs +13 -0
  46. package/dist/{export-QDkuuzSE.mjs → export-Bfk7JAlR.mjs} +30 -23
  47. package/dist/field-B3gvaqpK.mjs +278 -0
  48. package/dist/field-BDJ1pEgr.mjs +18 -0
  49. package/dist/fields-7ByLsxLg.mjs +38 -0
  50. package/dist/flag-pair-DtR1AiBQ.mjs +17 -0
  51. package/dist/get-BE6Izpus.mjs +36 -0
  52. package/dist/get-C3CcAJGg.mjs +49 -0
  53. package/dist/{get-DI_IJvgk.mjs → get-CQGeF-eP.mjs} +6 -4
  54. package/dist/get-D2m4jhwT.mjs +53 -0
  55. package/dist/{get-BGBIzMKY.mjs → get-DKy3DAJX.mjs} +6 -4
  56. package/dist/{get-COXHplHP.mjs → get-DUSR5i99.mjs} +7 -5
  57. package/dist/get-DikegGzi.mjs +36 -0
  58. package/dist/get-StkjKuh0.mjs +40 -0
  59. package/dist/get-bYc7eGYe.mjs +36 -0
  60. package/dist/{get-Cl8-IauC.mjs → get-cuHp9-6U.mjs} +7 -4
  61. package/dist/{get-i6LWOByV.mjs → get-gOT_RarI.mjs} +6 -4
  62. package/dist/get-run-D59Yqaoh.mjs +36 -0
  63. package/dist/get-tISo-cmg.mjs +41 -0
  64. package/dist/git-sync-BiTWfLgY.mjs +28 -0
  65. package/dist/{has-remote-changes-hjKoQuRy.mjs → has-remote-changes-B1TciDVD.mjs} +8 -6
  66. package/dist/{import-HJsSKRYx.mjs → import-DnnmmJbp.mjs} +11 -9
  67. package/dist/{input-Dojr-RTw.mjs → input-ikCiip6x.mjs} +2 -1
  68. package/dist/is-dirty-DClGFOGV.mjs +10 -0
  69. package/dist/{is-dirty-1Qy7hiHB.mjs → is-dirty-DlfX7e39.mjs} +5 -4
  70. package/dist/items-DQFQSpjF.mjs +77 -0
  71. package/dist/{key-DBxPSFwi.mjs → key-NDEARu2L.mjs} +1 -1
  72. package/dist/{license-MoWse3ZI.mjs → license-DBh13sc8.mjs} +3 -3
  73. package/dist/list-4kYCGv01.mjs +32 -0
  74. package/dist/list-9AOWhxqp.mjs +61 -0
  75. package/dist/{list-Bk6RsbJl.mjs → list-BwjqQ6pp.mjs} +5 -3
  76. package/dist/{list-C_PRdL5e.mjs → list-CP5RNjO6.mjs} +7 -5
  77. package/dist/{list-C8tdLOH5.mjs → list-Cy0VhXQs.mjs} +5 -3
  78. package/dist/list-D067ZSE5.mjs +47 -0
  79. package/dist/list-DAZP-IM5.mjs +32 -0
  80. package/dist/list-DJN-OvTZ.mjs +52 -0
  81. package/dist/list-DQj-QJAs.mjs +40 -0
  82. package/dist/list-Di529OJD.mjs +55 -0
  83. package/dist/{list-C4Ajrw8f.mjs → list-DlKzgnqo.mjs} +6 -3
  84. package/dist/list-GFfR9SuT.mjs +32 -0
  85. package/dist/{list-CWt3fqrZ.mjs → list-iFVEdi2J.mjs} +5 -3
  86. package/dist/{login-C9WTwNn6.mjs → login-DxgkosGx.mjs} +30 -9
  87. package/dist/{logout-oLszGCOg.mjs → logout-BlVwqBog.mjs} +7 -6
  88. package/dist/logs-CudNEkT4.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-C7SbdYQk.mjs +19 -0
  92. package/dist/metadata-B2Td415K.mjs +38 -0
  93. package/dist/metadata-BTJAFVvZ.mjs +37 -0
  94. package/dist/{package-BGfw4ZWJ.mjs → package-DV6Asqim.mjs} +7 -1
  95. package/dist/paginate-CTSfuYiF.mjs +49 -0
  96. package/dist/parse-id-B38zTlYs.mjs +12 -0
  97. package/dist/parse-ref-DGvh4aDn.mjs +17 -0
  98. package/dist/parse-schemas-Ds-cVE-O.mjs +12 -0
  99. package/dist/{poll-ILanYysl.mjs → poll-Bh6oAifO.mjs} +2 -1
  100. package/dist/{poll-task-DbpsiQhl.mjs → poll-task-vPwV31Fs.mjs} +8 -7
  101. package/dist/predicates-DiIiS3k7.mjs +153 -0
  102. package/dist/preflight-DxJb-hUV.mjs +91 -0
  103. package/dist/{prompt-DpT8yAVy.mjs → prompt-Bf3DQ-qE.mjs} +1 -1
  104. package/dist/provision-B-I0zuDe.mjs +77 -0
  105. package/dist/ps-BmYQYC7t.mjs +10 -0
  106. package/dist/ps-CaiOFCv2.mjs +78 -0
  107. package/dist/query-BtF1yWZZ.mjs +90 -0
  108. package/dist/{query-PihYi-UZ.mjs → query-jmfqaXRP.mjs} +38 -13
  109. package/dist/remove-C2iv0g03.mjs +98 -0
  110. package/dist/remove-collection-DhZghaZy.mjs +38 -0
  111. package/dist/{remove-B2hVYn1v.mjs → remove-xskleeru.mjs} +6 -5
  112. package/dist/render-DXv-D6fU.mjs +182 -0
  113. package/dist/rescan-values-DW6u90ep.mjs +43 -0
  114. package/dist/revision-message-flag-CWQbKhdl.mjs +11 -0
  115. package/dist/{run-C2so6Qp6.mjs → run-DxVzhcF3.mjs} +27 -36
  116. package/dist/runs-BOHk1XnM.mjs +54 -0
  117. package/dist/{runtime-C9CEZhcn.mjs → runtime-cwBS8wwK.mjs} +428 -442
  118. package/dist/schema-tables-CcFbY_jN.mjs +45 -0
  119. package/dist/schemas-DZmv_V62.mjs +47 -0
  120. package/dist/{search-CopOytXY.mjs → search-CYMuc7Fg.mjs} +6 -19
  121. package/dist/segment-BMrUBz94.mjs +70 -0
  122. package/dist/segment-Df4pfjco.mjs +19 -0
  123. package/dist/{set-BcF7M1GQ.mjs → set-B_rrVwU4.mjs} +6 -4
  124. package/dist/{set-CbibegpA.mjs → set-CbGfQ7Ye.mjs} +8 -6
  125. package/dist/{setting-U3NtBMFo.mjs → setting-DqZY9NXP.mjs} +3 -3
  126. package/dist/setup-DxmcAorA.mjs +71 -0
  127. package/dist/snippet-CwSHjQyn.mjs +19 -0
  128. package/dist/snippet-Dw0Sjzkr.mjs +64 -0
  129. package/dist/start-Cn0epTks.mjs +380 -0
  130. package/dist/{stash-DOBbYozC.mjs → stash-BFZIl9F4.mjs} +9 -7
  131. package/dist/{status-Buf1ZbNR.mjs → status-BjCeJNLp.mjs} +10 -8
  132. package/dist/{status-CUcs8XBH.mjs → status-FDIDmqvM.mjs} +4 -2
  133. package/dist/{status-D1F5XHae.mjs → status-UALK3OJl.mjs} +4 -2
  134. package/dist/stop-DUwrDWw8.mjs +81 -0
  135. package/dist/summary-CS4UGiFJ.mjs +41 -0
  136. package/dist/sync-schema-IrHdJxmX.mjs +43 -0
  137. package/dist/{table-Cfk7oSvw.mjs → table-B-PYcgGb.mjs} +22 -9
  138. package/dist/table-Cdr5bKp1.mjs +19 -0
  139. package/dist/transform-CeZusR_w.mjs +24 -0
  140. package/dist/{transform-B5uRpg1G.mjs → transform-IEX4Mx3X.mjs} +56 -2
  141. package/dist/transform-job-BOn9-CGa.mjs +19 -0
  142. package/dist/{transform-job-C7QXWTVE.mjs → transform-job-Csr86muI.mjs} +7 -0
  143. package/dist/translate-B__zbDKm.mjs +111 -0
  144. package/dist/tree-Mh0uQ_Wy.mjs +32 -0
  145. package/dist/update-1Di9hbPo.mjs +56 -0
  146. package/dist/update-B5_pp6Jj.mjs +56 -0
  147. package/dist/update-B9DBMo30.mjs +52 -0
  148. package/dist/update-BfBsM_y1.mjs +56 -0
  149. package/dist/update-Bw0WZix_.mjs +73 -0
  150. package/dist/update-Cp1789qq.mjs +52 -0
  151. package/dist/update-D2VI_5cy.mjs +57 -0
  152. package/dist/update-D8GwQTcL.mjs +59 -0
  153. package/dist/{update-CL8tRbxr.mjs → update-Masp5WeT.mjs} +9 -7
  154. package/dist/update-dashcard-CNiQw1MD.mjs +71 -0
  155. package/dist/update-j9vgemKR.mjs +51 -0
  156. package/dist/url-GFM76VIK.mjs +54 -0
  157. package/dist/uuid-Uif0lNk8.mjs +47 -0
  158. package/dist/validate-DCYx6jdL.mjs +1496 -0
  159. package/dist/validate-query-B07oGG4K.mjs +37 -0
  160. package/dist/values-DrwNHUAI.mjs +36 -0
  161. package/dist/{wait-Bugr9eXD.mjs → wait-BoKk8CJy.mjs} +10 -8
  162. package/dist/wait-DO7tS7NI.mjs +19 -0
  163. package/dist/wait-flags-CjX2sEGm.mjs +35 -0
  164. package/dist/workspace-CyEX40D-.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,17 @@
1
+ import { ConfigError } from "./predicates-DiIiS3k7.mjs";
2
+
3
+ //#region src/commands/collection/parse-ref.ts
4
+ const SPECIAL_TOKENS = new Set(["root", "trash"]);
5
+ const POSITIVE_INTEGER_PATTERN = /^[1-9]\d*$/;
6
+ const NANO_ID_PATTERN = /^[A-Za-z0-9_-]{21}$/;
7
+ const FORMAT_HINT = "expected integer, \"root\", \"trash\", or 21-char entity id";
8
+ function parseCollectionRef(raw) {
9
+ const trimmed = raw.trim();
10
+ if (trimmed === "") throw new ConfigError(`invalid id: ${JSON.stringify(trimmed)} (${FORMAT_HINT})`);
11
+ if (SPECIAL_TOKENS.has(trimmed)) return trimmed;
12
+ if (POSITIVE_INTEGER_PATTERN.test(trimmed) || NANO_ID_PATTERN.test(trimmed)) return trimmed;
13
+ throw new ConfigError(`invalid id: ${JSON.stringify(raw)} (${FORMAT_HINT})`);
14
+ }
15
+
16
+ //#endregion
17
+ export { parseCollectionRef };
@@ -0,0 +1,12 @@
1
+ import { ConfigError } from "./predicates-DiIiS3k7.mjs";
2
+ import { parseCsv } from "./runtime-cwBS8wwK.mjs";
3
+
4
+ //#region src/commands/workspace/database/parse-schemas.ts
5
+ function parseSchemasCsv(raw) {
6
+ const parts = parseCsv(raw);
7
+ if (parts.length === 0) throw new ConfigError("--schemas must contain at least one schema name");
8
+ return parts;
9
+ }
10
+
11
+ //#endregion
12
+ export { parseSchemasCsv };
@@ -1,4 +1,5 @@
1
- import { TimeoutError, combineAborts, throwIfAborted } from "./runtime-C9CEZhcn.mjs";
1
+ import { TimeoutError } from "./predicates-DiIiS3k7.mjs";
2
+ import { combineAborts, throwIfAborted } from "./runtime-cwBS8wwK.mjs";
2
3
  import { setTimeout } from "node:timers/promises";
3
4
 
4
5
  //#region src/runtime/poll.ts
@@ -1,8 +1,8 @@
1
- import { parseJson } from "./runtime-C9CEZhcn.mjs";
2
- import { DEFAULT_INTERVAL_MS, DEFAULT_TIMEOUT_MS, pollUntil } from "./poll-ILanYysl.mjs";
1
+ import { parseJsonOrPlain } from "./runtime-cwBS8wwK.mjs";
2
+ import { DEFAULT_INTERVAL_MS, DEFAULT_TIMEOUT_MS, pollUntil } from "./poll-Bh6oAifO.mjs";
3
3
  import { z } from "zod";
4
4
 
5
- //#region src/domain/remote-sync.ts
5
+ //#region src/domain/git-sync.ts
6
6
  const SyncTaskStatus = z.enum([
7
7
  "running",
8
8
  "successful",
@@ -109,7 +109,7 @@ const syncDirtyItemView = {
109
109
  };
110
110
 
111
111
  //#endregion
112
- //#region src/commands/sync/poll-task.ts
112
+ //#region src/commands/git-sync/poll-task.ts
113
113
  const TERMINAL_STATUSES = new Set([
114
114
  "successful",
115
115
  "errored",
@@ -132,7 +132,8 @@ const REMOTE_SYNC_PATHS = {
132
132
  export: "/api/ee/remote-sync/export",
133
133
  stash: "/api/ee/remote-sync/stash",
134
134
  branches: "/api/ee/remote-sync/branches",
135
- createBranch: "/api/ee/remote-sync/create-branch"
135
+ createBranch: "/api/ee/remote-sync/create-branch",
136
+ settings: "/api/ee/remote-sync/settings"
136
137
  };
137
138
  const SyncTaskIdle = z.object({ status: z.literal("idle") });
138
139
  const SyncTaskOrIdle = z.union([SyncTask, SyncTaskIdle]);
@@ -173,7 +174,7 @@ async function fetchOptionalParsed(client, path, schema) {
173
174
  });
174
175
  if (response.status === 204) return null;
175
176
  const text = await response.text();
176
- return parseJson(text, schema, { source: response.url });
177
+ return parseJsonOrPlain(text, response.headers.get("content-type"), schema, { source: response.url });
177
178
  }
178
179
  async function fetchCurrentTask(client) {
179
180
  return await fetchOptionalParsed(client, REMOTE_SYNC_PATHS.currentTask, SyncTask);
@@ -187,7 +188,7 @@ async function pollSyncTask(client, opts) {
187
188
  function throwIfFailedTask(final, verb) {
188
189
  if (final === null || !isFailure(final.status)) return;
189
190
  const detail = final.error_message ? `: ${final.error_message}` : "";
190
- throw new Error(`sync ${verb} ${final.status}${detail}`);
191
+ throw new Error(`git-sync ${verb} ${final.status}${detail}`);
191
192
  }
192
193
 
193
194
  //#endregion
@@ -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-cwBS8wwK.mjs";
4
+ import { Card } from "./card-CQxvHeyP.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-DV6Asqim.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-cwBS8wwK.mjs";
7
+ import { readBody } from "./body-rDrR-C1c.mjs";
8
+ import { bodyInputFlags } from "./body-flags-BK7J6Daz.mjs";
9
+ import { parseId } from "./parse-id-B38zTlYs.mjs";
10
+ import "./poll-Bh6oAifO.mjs";
11
+ import { parseWaitFlags, waitFlags } from "./wait-flags-CjX2sEGm.mjs";
12
+ import { Workspace, WorkspaceProvisionInput, workspaceView } from "./workspace-DVuqKJGG.mjs";
13
+ import { waitForDatabaseProvisioned } from "./wait-DO7tS7NI.mjs";
14
+ import { parseSchemasCsv } from "./parse-schemas-Ds-cVE-O.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-DV6Asqim.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import "./render-DXv-D6fU.mjs";
4
+ import "./predicates-DiIiS3k7.mjs";
5
+ import "./runtime-cwBS8wwK.mjs";
6
+ import "./poll-Bh6oAifO.mjs";
7
+ import "./docker-CHpV8PRz.mjs";
8
+ import { LocalWorkspace, LocalWorkspaceCompact, LocalWorkspaceListEnvelope, LocalWorkspaceState, localWorkspaceView, ps_default } from "./ps-CaiOFCv2.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-cwBS8wwK.mjs";
3
+ import { CONTAINER_STATES, checkDockerReady, listWorkspaceContainers } from "./docker-CHpV8PRz.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 };
@@ -0,0 +1,90 @@
1
+ import "./package-DV6Asqim.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-cwBS8wwK.mjs";
7
+ import { readBody } from "./body-rDrR-C1c.mjs";
8
+ import { bodyInputFlags } from "./body-flags-BK7J6Daz.mjs";
9
+ import "./field-B3gvaqpK.mjs";
10
+ import { CardQueryResult, cardQueryView } from "./card-CQxvHeyP.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 };