@metabase/cli 0.1.0-alpha.workspaces-commands.818a8f1

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 (107) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +762 -0
  3. package/dist/api-key-D9XxErQn.mjs +13 -0
  4. package/dist/archive-BPG5c88Y.mjs +38 -0
  5. package/dist/auth--Hpjwlaf.mjs +18 -0
  6. package/dist/body-DwU2s6Pg.mjs +19 -0
  7. package/dist/body-flags-7oqLhu5j.mjs +14 -0
  8. package/dist/branches-BbcoJXfp.mjs +41 -0
  9. package/dist/cancel-task-BDas45YO.mjs +29 -0
  10. package/dist/card-C31pGtBZ.mjs +113 -0
  11. package/dist/card-D4zZSPUb.mjs +19 -0
  12. package/dist/cli.d.mts +1 -0
  13. package/dist/cli.mjs +61 -0
  14. package/dist/command-augment-D9pI9Vbh.mjs +11 -0
  15. package/dist/create-Bd_U1zWU.mjs +124 -0
  16. package/dist/create-CCzsCZMm.mjs +47 -0
  17. package/dist/create-CwVcoq0O.mjs +43 -0
  18. package/dist/create-DpnjQvPw.mjs +43 -0
  19. package/dist/create-_UOeEXAj.mjs +39 -0
  20. package/dist/create-branch-sDttBORB.mjs +54 -0
  21. package/dist/credentials-C0xKke5D.mjs +84 -0
  22. package/dist/current-task-BGt1mqaX.mjs +35 -0
  23. package/dist/database-4V1iiPEx.mjs +17 -0
  24. package/dist/database-BTX5qbSv.mjs +33 -0
  25. package/dist/db-Dm2u2ISJ.mjs +17 -0
  26. package/dist/delete-DRBTgyus.mjs +47 -0
  27. package/dist/delete-DUC_stoL.mjs +47 -0
  28. package/dist/delete-runtime-inOVw3IX.mjs +58 -0
  29. package/dist/delete-table-9Is631O_.mjs +47 -0
  30. package/dist/deprovision-BAMzZc6f.mjs +60 -0
  31. package/dist/dirty-CLjHbz6J.mjs +32 -0
  32. package/dist/docker-QWVMG2gl.mjs +605 -0
  33. package/dist/eid-BNhutC1U.mjs +13 -0
  34. package/dist/export-D2Anfu3p.mjs +97 -0
  35. package/dist/field-Dhs2AND3.mjs +13 -0
  36. package/dist/field-QwBMAWsq.mjs +76 -0
  37. package/dist/flag-pair-CWvvzDJ_.mjs +17 -0
  38. package/dist/get-2po1uv9i.mjs +35 -0
  39. package/dist/get-BHJA78zg.mjs +35 -0
  40. package/dist/get-CAPLfawI.mjs +35 -0
  41. package/dist/get-CAVVmdMX.mjs +49 -0
  42. package/dist/get-DDWpubE8.mjs +36 -0
  43. package/dist/get-DhIoNeOp.mjs +35 -0
  44. package/dist/get-qPOsuTPw.mjs +35 -0
  45. package/dist/has-remote-changes-DAL5jetW.mjs +63 -0
  46. package/dist/import-CUMxUfSF.mjs +92 -0
  47. package/dist/input-BNqSFl38.mjs +33 -0
  48. package/dist/is-dirty-B10S6MG0.mjs +35 -0
  49. package/dist/is-dirty-CUuq-aB6.mjs +9 -0
  50. package/dist/key-CyhOpgWt.mjs +12 -0
  51. package/dist/license-DtsGJi3l.mjs +17 -0
  52. package/dist/list-B8s7Qnzk.mjs +31 -0
  53. package/dist/list-C5MGydGU.mjs +31 -0
  54. package/dist/list-DeFGwhhJ.mjs +60 -0
  55. package/dist/list-OBx5B3gd.mjs +39 -0
  56. package/dist/list-Y7iGsOfE.mjs +31 -0
  57. package/dist/list-evtQS7jl.mjs +39 -0
  58. package/dist/list-qetY9OIN.mjs +31 -0
  59. package/dist/login-Dqw9ZtCx.mjs +172 -0
  60. package/dist/logout-DwYJ5OUi.mjs +74 -0
  61. package/dist/logs-B_lrY7Js.mjs +57 -0
  62. package/dist/manifest-wzEFG0JB.mjs +124 -0
  63. package/dist/package-t8dKf4m_.mjs +73 -0
  64. package/dist/parse-id-C1prc9US.mjs +12 -0
  65. package/dist/poll-D2sXM5rc.mjs +49 -0
  66. package/dist/poll-task-Byiunmaj.mjs +194 -0
  67. package/dist/prompt-fXeNtj0M.mjs +40 -0
  68. package/dist/provision-DC4_HWZD.mjs +80 -0
  69. package/dist/ps-1bZKIwWh.mjs +9 -0
  70. package/dist/ps-BiOrecEe.mjs +78 -0
  71. package/dist/query-BnGVGeM3.mjs +100 -0
  72. package/dist/remove-Bx48o-0S.mjs +62 -0
  73. package/dist/remove-DecoZzNd.mjs +97 -0
  74. package/dist/render-DlBijc5i.mjs +179 -0
  75. package/dist/run-D4NgvaRh.mjs +87 -0
  76. package/dist/runtime-DUgFfYkN.mjs +950 -0
  77. package/dist/search-4wKx5ug2.mjs +171 -0
  78. package/dist/set-BZnCRL4c.mjs +66 -0
  79. package/dist/set-DCjrmTFm.mjs +66 -0
  80. package/dist/setting-C4vQSqer.mjs +18 -0
  81. package/dist/setting-DM7pm7yh.mjs +55 -0
  82. package/dist/setup-Dqh9hN6l.mjs +70 -0
  83. package/dist/start-xXQypG5L.mjs +324 -0
  84. package/dist/stash-ZZkmW_V7.mjs +106 -0
  85. package/dist/status-9KAPIpX8.mjs +31 -0
  86. package/dist/status-DezF-PIM.mjs +63 -0
  87. package/dist/status-JH6BZppo.mjs +55 -0
  88. package/dist/stop-br-ZOnve.mjs +80 -0
  89. package/dist/sync-C7VOWD00.mjs +26 -0
  90. package/dist/table-BvAr2ixC.mjs +75 -0
  91. package/dist/table-D-Mb5Nvw.mjs +16 -0
  92. package/dist/transform-CqxZwhGs.mjs +21 -0
  93. package/dist/transform-DfVkUttP.mjs +137 -0
  94. package/dist/transform-job-DuB_OjhO.mjs +91 -0
  95. package/dist/transform-job-HjbqjEoP.mjs +19 -0
  96. package/dist/translate-DJxDVAE4.mjs +110 -0
  97. package/dist/update-CDtm71m2.mjs +50 -0
  98. package/dist/update-DYVeVjk2.mjs +76 -0
  99. package/dist/update-DxKlQ0hP.mjs +50 -0
  100. package/dist/url-DP88YHNo.mjs +53 -0
  101. package/dist/wait-Cj_8wu4y.mjs +52 -0
  102. package/dist/wait-DwZN3ZwR.mjs +19 -0
  103. package/dist/wait-flags-CjW4ogUJ.mjs +35 -0
  104. package/dist/workspace-CbwR0vX_.mjs +24 -0
  105. package/dist/workspace-Dr9lWU3D.mjs +72 -0
  106. package/dist/workspace-credentials-q5RRFMT8.mjs +139 -0
  107. package/package.json +62 -0
@@ -0,0 +1,35 @@
1
+ import { renderItem } from "./render-DlBijc5i.mjs";
2
+ import { connectionFlags, defineMetabaseCommand, outputFlags, profileFlag } from "./runtime-DUgFfYkN.mjs";
3
+ import { REMOTE_SYNC_PATHS } from "./poll-task-Byiunmaj.mjs";
4
+ import { z } from "zod";
5
+
6
+ //#region src/commands/sync/is-dirty.ts
7
+ const IsDirtyResult = z.object({ is_dirty: z.boolean() });
8
+ const isDirtyView = {
9
+ compactPick: IsDirtyResult,
10
+ tableColumns: [{
11
+ key: "is_dirty",
12
+ label: "Dirty"
13
+ }]
14
+ };
15
+ var is_dirty_default = defineMetabaseCommand({
16
+ meta: {
17
+ name: "is-dirty",
18
+ description: "Check whether Metabase has unsynced local changes"
19
+ },
20
+ args: {
21
+ ...outputFlags,
22
+ ...profileFlag,
23
+ ...connectionFlags
24
+ },
25
+ outputSchema: IsDirtyResult,
26
+ examples: ["metabase sync is-dirty", "metabase sync is-dirty --json"],
27
+ async run({ ctx, getClient }) {
28
+ const client = await getClient();
29
+ const result = await client.requestParsed(IsDirtyResult, REMOTE_SYNC_PATHS.isDirty);
30
+ renderItem(result, isDirtyView, ctx);
31
+ }
32
+ });
33
+
34
+ //#endregion
35
+ export { IsDirtyResult, is_dirty_default };
@@ -0,0 +1,9 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import "./render-DlBijc5i.mjs";
4
+ import "./runtime-DUgFfYkN.mjs";
5
+ import "./poll-task-Byiunmaj.mjs";
6
+ import "./poll-D2sXM5rc.mjs";
7
+ import { IsDirtyResult, is_dirty_default } from "./is-dirty-B10S6MG0.mjs";
8
+
9
+ export { is_dirty_default as default };
@@ -0,0 +1,12 @@
1
+ import { ConfigError } from "./runtime-DUgFfYkN.mjs";
2
+
3
+ //#region src/commands/setting/key.ts
4
+ const SETTING_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
5
+ function parseSettingKey(value) {
6
+ const trimmed = value.trim();
7
+ if (!SETTING_KEY_PATTERN.test(trimmed)) throw new ConfigError(`invalid setting key: "${value}" (expected kebab-case identifier)`);
8
+ return trimmed;
9
+ }
10
+
11
+ //#endregion
12
+ export { parseSettingKey };
@@ -0,0 +1,17 @@
1
+ import { defineCommand } from "citty";
2
+
3
+ //#region src/commands/license/index.ts
4
+ var license_default = defineCommand({
5
+ meta: {
6
+ name: "license",
7
+ description: "Manage the Metabase license token"
8
+ },
9
+ subCommands: {
10
+ set: () => import("./set-BZnCRL4c.mjs").then((m) => m.default),
11
+ status: () => import("./status-9KAPIpX8.mjs").then((m) => m.default),
12
+ remove: () => import("./remove-Bx48o-0S.mjs").then((m) => m.default)
13
+ }
14
+ });
15
+
16
+ //#endregion
17
+ export { license_default as default };
@@ -0,0 +1,31 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { Workspace, WorkspaceCompact, workspaceView } from "./workspace-Dr9lWU3D.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/workspace/list.ts
9
+ const WorkspaceApiList = z.array(Workspace);
10
+ const WorkspaceListEnvelope = listEnvelopeSchema(WorkspaceCompact);
11
+ var list_default = defineMetabaseCommand({
12
+ meta: {
13
+ name: "list",
14
+ description: "List workspaces"
15
+ },
16
+ args: {
17
+ ...outputFlags,
18
+ ...profileFlag,
19
+ ...connectionFlags
20
+ },
21
+ outputSchema: WorkspaceListEnvelope,
22
+ examples: ["metabase workspace list", "metabase workspace list --json"],
23
+ async run({ ctx, getClient }) {
24
+ const client = await getClient();
25
+ const items = await client.requestParsed(WorkspaceApiList, "/api/ee/workspace-manager");
26
+ renderList(wrapList(items), workspaceView, ctx);
27
+ }
28
+ });
29
+
30
+ //#endregion
31
+ export { list_default as default };
@@ -0,0 +1,31 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { TransformJob, TransformJobCompact, transformJobView } from "./transform-job-DuB_OjhO.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/transform-job/list.ts
9
+ const TransformJobApiList = z.array(TransformJob);
10
+ const TransformJobListEnvelope = listEnvelopeSchema(TransformJobCompact);
11
+ var list_default = defineMetabaseCommand({
12
+ meta: {
13
+ name: "list",
14
+ description: "List transform jobs"
15
+ },
16
+ args: {
17
+ ...outputFlags,
18
+ ...profileFlag,
19
+ ...connectionFlags
20
+ },
21
+ outputSchema: TransformJobListEnvelope,
22
+ examples: ["metabase transform-job list", "metabase transform-job list --json"],
23
+ async run({ ctx, getClient }) {
24
+ const client = await getClient();
25
+ const items = await client.requestParsed(TransformJobApiList, "/api/transform-job");
26
+ renderList(wrapList(items), transformJobView, ctx);
27
+ }
28
+ });
29
+
30
+ //#endregion
31
+ export { list_default as default };
@@ -0,0 +1,60 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { Card, CardCompact, cardView } from "./card-C31pGtBZ.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/card/list.ts
9
+ const CardApiList = z.array(Card);
10
+ const CardListFilter = z.enum([
11
+ "all",
12
+ "mine",
13
+ "bookmarked",
14
+ "database",
15
+ "table",
16
+ "archived",
17
+ "using_model",
18
+ "using_segment"
19
+ ]);
20
+ const CardListEnvelope = listEnvelopeSchema(CardCompact);
21
+ var list_default = defineMetabaseCommand({
22
+ meta: {
23
+ name: "list",
24
+ description: "List cards (questions, models, metrics)"
25
+ },
26
+ args: {
27
+ ...outputFlags,
28
+ ...profileFlag,
29
+ ...connectionFlags,
30
+ filter: {
31
+ type: "string",
32
+ description: `Filter preset: ${CardListFilter.options.join("|")}`,
33
+ default: "all"
34
+ },
35
+ modelId: {
36
+ type: "string",
37
+ description: "Used by filter database|table|using_model|using_segment",
38
+ alias: "model-id"
39
+ }
40
+ },
41
+ outputSchema: CardListEnvelope,
42
+ examples: [
43
+ "metabase card list",
44
+ "metabase card list --filter archived --json",
45
+ "metabase card list --filter using_model --model-id 42 --json"
46
+ ],
47
+ async run({ args, ctx, getClient }) {
48
+ const filter = CardListFilter.parse(args.filter);
49
+ const modelId = args.modelId === void 0 || args.modelId === "" ? void 0 : args.modelId;
50
+ const client = await getClient();
51
+ const items = await client.requestParsed(CardApiList, "/api/card", { query: {
52
+ f: filter,
53
+ model_id: modelId
54
+ } });
55
+ renderList(wrapList(items), cardView, ctx);
56
+ }
57
+ });
58
+
59
+ //#endregion
60
+ export { list_default as default };
@@ -0,0 +1,39 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { parseId } from "./parse-id-C1prc9US.mjs";
6
+ import "./field-QwBMAWsq.mjs";
7
+ import { Table, TableCompact, tableView } from "./table-BvAr2ixC.mjs";
8
+ import { z } from "zod";
9
+
10
+ //#region src/commands/table/list.ts
11
+ const TableApiList = z.array(Table);
12
+ const TableListEnvelope = listEnvelopeSchema(TableCompact);
13
+ var list_default = defineMetabaseCommand({
14
+ meta: {
15
+ name: "list",
16
+ description: "List tables (optionally filtered by database)"
17
+ },
18
+ args: {
19
+ ...outputFlags,
20
+ ...profileFlag,
21
+ ...connectionFlags,
22
+ "db-id": {
23
+ type: "string",
24
+ description: "Filter by database id"
25
+ }
26
+ },
27
+ outputSchema: TableListEnvelope,
28
+ examples: ["metabase table list", "metabase table list --db-id 1 --json"],
29
+ async run({ args, ctx, getClient }) {
30
+ const dbIdFilter = args["db-id"] === void 0 ? void 0 : parseId(args["db-id"], "db-id");
31
+ const client = await getClient();
32
+ const all = await client.requestParsed(TableApiList, "/api/table");
33
+ const filtered = dbIdFilter === void 0 ? all : all.filter((row) => row.db_id === dbIdFilter);
34
+ renderList(wrapList(filtered), tableView, ctx);
35
+ }
36
+ });
37
+
38
+ //#endregion
39
+ export { list_default as default };
@@ -0,0 +1,31 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { Setting, SettingCompact, settingView } from "./setting-DM7pm7yh.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/setting/list.ts
9
+ const SettingApiList = z.array(Setting);
10
+ const SettingListEnvelope = listEnvelopeSchema(SettingCompact);
11
+ var list_default = defineMetabaseCommand({
12
+ meta: {
13
+ name: "list",
14
+ description: "List all settings (admin)"
15
+ },
16
+ args: {
17
+ ...outputFlags,
18
+ ...profileFlag,
19
+ ...connectionFlags
20
+ },
21
+ outputSchema: SettingListEnvelope,
22
+ examples: ["metabase setting list", "metabase setting list --json"],
23
+ async run({ ctx, getClient }) {
24
+ const client = await getClient();
25
+ const settings = await client.requestParsed(SettingApiList, "/api/setting");
26
+ renderList(wrapList(settings), settingView, ctx);
27
+ }
28
+ });
29
+
30
+ //#endregion
31
+ export { list_default as default };
@@ -0,0 +1,39 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag } from "./runtime-DUgFfYkN.mjs";
5
+ import { Database, DatabaseCompact, databaseView } from "./database-BTX5qbSv.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/db/list.ts
9
+ const DatabaseApiList = z.object({
10
+ data: z.array(Database),
11
+ total: z.number().int().nonnegative()
12
+ }).loose();
13
+ const DatabaseListEnvelope = listEnvelopeSchema(DatabaseCompact);
14
+ var list_default = defineMetabaseCommand({
15
+ meta: {
16
+ name: "list",
17
+ description: "List databases"
18
+ },
19
+ args: {
20
+ ...outputFlags,
21
+ ...profileFlag,
22
+ ...connectionFlags
23
+ },
24
+ outputSchema: DatabaseListEnvelope,
25
+ examples: ["metabase db list", "metabase db list --json"],
26
+ async run({ ctx, getClient }) {
27
+ const client = await getClient();
28
+ const response = await client.requestParsed(DatabaseApiList, "/api/database");
29
+ const envelope = {
30
+ data: response.data,
31
+ returned: response.data.length,
32
+ total: response.total
33
+ };
34
+ renderList(envelope, databaseView, ctx);
35
+ }
36
+ });
37
+
38
+ //#endregion
39
+ export { list_default as default };
@@ -0,0 +1,31 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderList } from "./render-DlBijc5i.mjs";
4
+ import { connectionFlags, defineMetabaseCommand, listEnvelopeSchema, outputFlags, profileFlag, wrapList } from "./runtime-DUgFfYkN.mjs";
5
+ import { Transform, TransformCompact, transformView } from "./transform-DfVkUttP.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/transform/list.ts
9
+ const TransformApiList = z.array(Transform);
10
+ const TransformListEnvelope = listEnvelopeSchema(TransformCompact);
11
+ var list_default = defineMetabaseCommand({
12
+ meta: {
13
+ name: "list",
14
+ description: "List transforms"
15
+ },
16
+ args: {
17
+ ...outputFlags,
18
+ ...profileFlag,
19
+ ...connectionFlags
20
+ },
21
+ outputSchema: TransformListEnvelope,
22
+ examples: ["metabase transform list", "metabase transform list --json"],
23
+ async run({ ctx, getClient }) {
24
+ const client = await getClient();
25
+ const items = await client.requestParsed(TransformApiList, "/api/transform");
26
+ renderList(wrapList(items), transformView, ctx);
27
+ }
28
+ });
29
+
30
+ //#endregion
31
+ export { list_default as default };
@@ -0,0 +1,172 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderItem, warn } from "./render-DlBijc5i.mjs";
4
+ import { ConfigError, HttpError, MetabaseError, connectionFlags, createClient, defineMetabaseCommand, errorMessage, normalizeUrl, outputFlags, profileFlag, readEnvCredentials, resolveProfileName, writeProfile } from "./runtime-DUgFfYkN.mjs";
5
+ import { readInput } from "./input-BNqSFl38.mjs";
6
+ import { promptPassword, promptText } from "./prompt-fXeNtj0M.mjs";
7
+ import { z } from "zod";
8
+
9
+ //#region src/domain/user.ts
10
+ const CurrentUser = z.object({
11
+ id: z.number().int(),
12
+ email: z.email()
13
+ }).loose();
14
+ const CurrentUserCompact = CurrentUser.pick({
15
+ id: true,
16
+ email: true
17
+ }).strip();
18
+
19
+ //#endregion
20
+ //#region src/core/auth/verify.ts
21
+ const VERIFY_TIMEOUT_MS = 15e3;
22
+ async function verifyCredentials(url, apiKey) {
23
+ const client = createClient({
24
+ url,
25
+ apiKey
26
+ });
27
+ try {
28
+ const user = await client.requestParsed(CurrentUser, "/api/user/current", {
29
+ timeoutMs: VERIFY_TIMEOUT_MS,
30
+ retries: 0
31
+ });
32
+ return {
33
+ ok: true,
34
+ user
35
+ };
36
+ } catch (error) {
37
+ return failure(error);
38
+ }
39
+ }
40
+ function failure(error) {
41
+ if (error instanceof HttpError) return {
42
+ ok: false,
43
+ status: error.status,
44
+ message: error.userMessage
45
+ };
46
+ if (error instanceof MetabaseError) return {
47
+ ok: false,
48
+ message: error.userMessage
49
+ };
50
+ return {
51
+ ok: false,
52
+ message: errorMessage(error)
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ //#region src/commands/auth/login.ts
58
+ const LoginResult = z.object({
59
+ profile: z.string(),
60
+ url: z.string(),
61
+ authenticated: z.boolean(),
62
+ email: z.string().nullable()
63
+ });
64
+ const loginView = {
65
+ compactPick: LoginResult,
66
+ tableColumns: [
67
+ {
68
+ key: "profile",
69
+ label: "Profile"
70
+ },
71
+ {
72
+ key: "url",
73
+ label: "URL"
74
+ },
75
+ {
76
+ key: "authenticated",
77
+ label: "Authenticated"
78
+ },
79
+ {
80
+ key: "email",
81
+ label: "Email"
82
+ }
83
+ ]
84
+ };
85
+ var login_default = defineMetabaseCommand({
86
+ meta: {
87
+ name: "login",
88
+ description: "Set Metabase credentials for a profile"
89
+ },
90
+ args: {
91
+ ...outputFlags,
92
+ ...profileFlag,
93
+ ...connectionFlags,
94
+ "skip-verify": {
95
+ type: "boolean",
96
+ default: false,
97
+ description: "Save without contacting the server"
98
+ }
99
+ },
100
+ outputSchema: LoginResult,
101
+ examples: [
102
+ "metabase auth login --url https://metabase.example.com < key.txt",
103
+ "echo $METABASE_API_KEY | metabase auth login --url https://metabase.example.com",
104
+ "metabase auth login --profile staging --url https://staging.example.com"
105
+ ],
106
+ async run({ args, ctx }) {
107
+ const profileName = resolveProfileName(args.profile);
108
+ const env = readEnvCredentials();
109
+ if (args.apiKey) warn("warning: --api-key is visible in shell history and process listings — pipe the key on stdin or set METABASE_API_KEY instead");
110
+ const url = await resolveUrl(args.url, env.url);
111
+ const apiKey = await resolveApiKey(args.apiKey, env.apiKey);
112
+ let email = null;
113
+ let authenticated = false;
114
+ if (!args["skip-verify"]) {
115
+ const result = await verifyCredentials(url, apiKey);
116
+ if (!result.ok) throw new ConfigError(`verification failed: ${result.message}`);
117
+ email = result.user.email;
118
+ authenticated = true;
119
+ }
120
+ const location = await writeProfile({
121
+ url,
122
+ apiKey
123
+ }, profileName);
124
+ if (location.backend === "file") warn(`warning: OS keychain unavailable; credentials stored as plaintext at ${location.path}`);
125
+ renderItem({
126
+ profile: profileName,
127
+ url,
128
+ authenticated,
129
+ email
130
+ }, loginView, ctx);
131
+ }
132
+ });
133
+ async function resolveUrl(flagUrl, envUrl) {
134
+ if (flagUrl) return normalizeUrl(flagUrl);
135
+ if (envUrl) return normalizeUrl(envUrl);
136
+ return promptForUrl();
137
+ }
138
+ async function resolveApiKey(flagKey, envKey) {
139
+ if (flagKey) return flagKey;
140
+ const piped = (await readInput({ required: false })).trim();
141
+ if (piped) return piped;
142
+ if (envKey) return envKey;
143
+ return promptForApiKey();
144
+ }
145
+ async function promptForUrl() {
146
+ if (!process.stdin.isTTY) throw new ConfigError("--url is required when stdin is not a TTY (cannot prompt interactively)");
147
+ const value = await promptText({
148
+ message: "Metabase URL",
149
+ placeholder: "https://metabase.example.com",
150
+ validate(input) {
151
+ if (!input) return "URL is required";
152
+ try {
153
+ normalizeUrl(input);
154
+ } catch (error) {
155
+ return errorMessage(error);
156
+ }
157
+ return void 0;
158
+ }
159
+ });
160
+ return normalizeUrl(value);
161
+ }
162
+ async function promptForApiKey() {
163
+ if (!process.stdin.isTTY) throw new ConfigError("--api-key, piped stdin, or METABASE_API_KEY required when stdin is not a TTY");
164
+ return promptPassword({
165
+ message: "API key",
166
+ mask: "•",
167
+ validate: (input) => input ? void 0 : "API key is required"
168
+ });
169
+ }
170
+
171
+ //#endregion
172
+ export { login_default as default };
@@ -0,0 +1,74 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { renderItem } from "./render-DlBijc5i.mjs";
4
+ import { ConfigError, clearProfile, defineMetabaseCommand, outputFlags, profileFlag, resolveProfileName } from "./runtime-DUgFfYkN.mjs";
5
+ import { promptConfirm } from "./prompt-fXeNtj0M.mjs";
6
+ import { z } from "zod";
7
+
8
+ //#region src/commands/auth/logout.ts
9
+ const LogoutResult = z.object({
10
+ profile: z.string(),
11
+ cleared: z.boolean(),
12
+ aborted: z.boolean()
13
+ });
14
+ const logoutView = {
15
+ compactPick: LogoutResult,
16
+ tableColumns: [
17
+ {
18
+ key: "profile",
19
+ label: "Profile"
20
+ },
21
+ {
22
+ key: "cleared",
23
+ label: "Cleared"
24
+ },
25
+ {
26
+ key: "aborted",
27
+ label: "Aborted"
28
+ }
29
+ ]
30
+ };
31
+ var logout_default = defineMetabaseCommand({
32
+ meta: {
33
+ name: "logout",
34
+ description: "Clear stored credentials for a profile"
35
+ },
36
+ args: {
37
+ ...outputFlags,
38
+ ...profileFlag,
39
+ yes: {
40
+ type: "boolean",
41
+ description: "Skip confirmation",
42
+ default: false
43
+ }
44
+ },
45
+ outputSchema: LogoutResult,
46
+ examples: ["metabase auth logout --yes", "metabase auth logout --profile staging --yes"],
47
+ async run({ args, ctx }) {
48
+ const profileName = resolveProfileName(args.profile);
49
+ if (!args.yes) {
50
+ if (!process.stdin.isTTY) throw new ConfigError("--yes required to clear credentials non-interactively");
51
+ const ok = await promptConfirm({
52
+ message: `Clear stored credentials for profile "${profileName}"?`,
53
+ initialValue: false
54
+ });
55
+ if (!ok) {
56
+ renderItem({
57
+ profile: profileName,
58
+ cleared: false,
59
+ aborted: true
60
+ }, logoutView, ctx);
61
+ return;
62
+ }
63
+ }
64
+ const cleared = await clearProfile(profileName);
65
+ renderItem({
66
+ profile: profileName,
67
+ cleared,
68
+ aborted: false
69
+ }, logoutView, ctx);
70
+ }
71
+ });
72
+
73
+ //#endregion
74
+ export { logout_default as default };
@@ -0,0 +1,57 @@
1
+ import "./package-t8dKf4m_.mjs";
2
+ import "./command-augment-D9pI9Vbh.mjs";
3
+ import { ConfigError, defineMetabaseCommand, outputFlags, parseInteger } from "./runtime-DUgFfYkN.mjs";
4
+ import { parseId } from "./parse-id-C1prc9US.mjs";
5
+ import "./poll-D2sXM5rc.mjs";
6
+ import { checkDockerReady, containerLifecycleStatus, containerNameFor, streamLogs } from "./docker-QWVMG2gl.mjs";
7
+
8
+ //#region src/commands/workspace/logs.ts
9
+ const DEFAULT_TAIL = 200;
10
+ var logs_default = defineMetabaseCommand({
11
+ meta: {
12
+ name: "logs",
13
+ description: "Stream the local container's logs (passthrough to `docker logs`)"
14
+ },
15
+ args: {
16
+ ...outputFlags,
17
+ id: {
18
+ type: "positional",
19
+ description: "Workspace id",
20
+ required: true
21
+ },
22
+ follow: {
23
+ type: "boolean",
24
+ alias: "f",
25
+ description: "Follow log output (stream indefinitely; Ctrl-C to exit)",
26
+ default: false
27
+ },
28
+ tail: {
29
+ type: "string",
30
+ description: `Number of lines from the end of the logs (default: ${DEFAULT_TAIL})`,
31
+ default: String(DEFAULT_TAIL)
32
+ }
33
+ },
34
+ examples: [
35
+ "metabase workspace logs 1",
36
+ "metabase workspace logs 1 --follow",
37
+ "metabase workspace logs 1 --tail 500"
38
+ ],
39
+ async run({ args }) {
40
+ const workspaceId = parseId(args.id);
41
+ const containerName = containerNameFor(workspaceId);
42
+ const tail = parseInteger(args.tail ?? String(DEFAULT_TAIL), {
43
+ name: "--tail",
44
+ min: 0
45
+ });
46
+ await checkDockerReady();
47
+ const status = await containerLifecycleStatus(containerName);
48
+ if (status === "missing") throw new ConfigError(`no container for workspace ${workspaceId} — run \`metabase workspace start ${workspaceId}\` first`);
49
+ await streamLogs(containerName, {
50
+ follow: args.follow === true,
51
+ tail
52
+ });
53
+ }
54
+ });
55
+
56
+ //#endregion
57
+ export { logs_default as default };