@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.
- package/README.md +972 -57
- package/dist/add-collection-DwxQDXzL.mjs +54 -0
- package/dist/add-collection-SL08iMub.mjs +11 -0
- package/dist/api-key-BktzvPb7.mjs +13 -0
- package/dist/{archive-CsWeHXle.mjs → archive-C1mF-9Kj.mjs} +7 -4
- package/dist/archive-CLWtbvvH.mjs +44 -0
- package/dist/archive-Cq4WKmJt.mjs +44 -0
- package/dist/archive-kYoy5LK5.mjs +39 -0
- package/dist/auth-DfYkakP3.mjs +19 -0
- package/dist/{body-Dv9hQ0Qk.mjs → body-rDrR-C1c.mjs} +3 -2
- package/dist/{branches-BujtceGr.mjs → branches-CH2UcCpX.mjs} +8 -6
- package/dist/cancel-CgLZcItQ.mjs +56 -0
- package/dist/{cancel-task-CT2xUMRg.mjs → cancel-task-DcYrFsM6.mjs} +9 -7
- package/dist/{card-CsXk8T6A.mjs → card-CQxvHeyP.mjs} +34 -15
- package/dist/card-ZCGU2JEh.mjs +20 -0
- package/dist/cards-C4NIaERo.mjs +37 -0
- package/dist/cli.mjs +33 -14
- package/dist/collection-B3sPXRLs.mjs +163 -0
- package/dist/collection-D_uFLIAS.mjs +19 -0
- package/dist/create-BUCLNqiN.mjs +48 -0
- package/dist/create-CB0Yp__0.mjs +66 -0
- package/dist/create-CNvd5T8h.mjs +48 -0
- package/dist/create-Cbh1cGj9.mjs +48 -0
- package/dist/create-CzfNOhOF.mjs +48 -0
- package/dist/create-DU0ZhnZu.mjs +44 -0
- package/dist/create-Dh0p-c2Y.mjs +44 -0
- package/dist/create-DvrVZ2hS.mjs +125 -0
- package/dist/create-QgN369N5.mjs +50 -0
- package/dist/{create-B8ektf-R.mjs → create-bqc_rmix.mjs} +8 -6
- package/dist/{create-branch-goZBTNnr.mjs → create-branch-BJFH9Hda.mjs} +9 -7
- package/dist/credentials-DTP1xuKz.mjs +85 -0
- package/dist/{current-task-DBjRNCFq.mjs → current-task-z_TiJ0kt.mjs} +9 -7
- package/dist/dashboard-CnMD04PQ.mjs +163 -0
- package/dist/dashboard-G1-dGLUR.mjs +20 -0
- package/dist/database-DQkUxTLd.mjs +17 -0
- package/dist/database-vvig8k4x.mjs +51 -0
- package/dist/db-CBaEfumR.mjs +22 -0
- package/dist/{delete-8vGU35r3.mjs → delete-CVYII8mq.mjs} +7 -5
- package/dist/{delete-B27KLF5X.mjs → delete-DeZQ1r9w.mjs} +7 -5
- package/dist/{delete-runtime-Byr60cR3.mjs → delete-runtime-BMzvfj_B.mjs} +4 -4
- package/dist/{delete-table-BNaJ_gA4.mjs → delete-table-ZiR9-ndv.mjs} +7 -5
- package/dist/deprovision-BhD3J-Am.mjs +61 -0
- package/dist/{dirty-aNUuph4I.mjs → dirty-D9agt7Os.mjs} +8 -6
- package/dist/docker-CHpV8PRz.mjs +612 -0
- package/dist/eid-B5wawMmO.mjs +13 -0
- package/dist/{export-QDkuuzSE.mjs → export-Bfk7JAlR.mjs} +30 -23
- package/dist/field-B3gvaqpK.mjs +278 -0
- package/dist/field-BDJ1pEgr.mjs +18 -0
- package/dist/fields-7ByLsxLg.mjs +38 -0
- package/dist/flag-pair-DtR1AiBQ.mjs +17 -0
- package/dist/get-BE6Izpus.mjs +36 -0
- package/dist/get-C3CcAJGg.mjs +49 -0
- package/dist/{get-DI_IJvgk.mjs → get-CQGeF-eP.mjs} +6 -4
- package/dist/get-D2m4jhwT.mjs +53 -0
- package/dist/{get-BGBIzMKY.mjs → get-DKy3DAJX.mjs} +6 -4
- package/dist/{get-COXHplHP.mjs → get-DUSR5i99.mjs} +7 -5
- package/dist/get-DikegGzi.mjs +36 -0
- package/dist/get-StkjKuh0.mjs +40 -0
- package/dist/get-bYc7eGYe.mjs +36 -0
- package/dist/{get-Cl8-IauC.mjs → get-cuHp9-6U.mjs} +7 -4
- package/dist/{get-i6LWOByV.mjs → get-gOT_RarI.mjs} +6 -4
- package/dist/get-run-D59Yqaoh.mjs +36 -0
- package/dist/get-tISo-cmg.mjs +41 -0
- package/dist/git-sync-BiTWfLgY.mjs +28 -0
- package/dist/{has-remote-changes-hjKoQuRy.mjs → has-remote-changes-B1TciDVD.mjs} +8 -6
- package/dist/{import-HJsSKRYx.mjs → import-DnnmmJbp.mjs} +11 -9
- package/dist/{input-Dojr-RTw.mjs → input-ikCiip6x.mjs} +2 -1
- package/dist/is-dirty-DClGFOGV.mjs +10 -0
- package/dist/{is-dirty-1Qy7hiHB.mjs → is-dirty-DlfX7e39.mjs} +5 -4
- package/dist/items-DQFQSpjF.mjs +77 -0
- package/dist/{key-DBxPSFwi.mjs → key-NDEARu2L.mjs} +1 -1
- package/dist/{license-MoWse3ZI.mjs → license-DBh13sc8.mjs} +3 -3
- package/dist/list-4kYCGv01.mjs +32 -0
- package/dist/list-9AOWhxqp.mjs +61 -0
- package/dist/{list-Bk6RsbJl.mjs → list-BwjqQ6pp.mjs} +5 -3
- package/dist/{list-C_PRdL5e.mjs → list-CP5RNjO6.mjs} +7 -5
- package/dist/{list-C8tdLOH5.mjs → list-Cy0VhXQs.mjs} +5 -3
- package/dist/list-D067ZSE5.mjs +47 -0
- package/dist/list-DAZP-IM5.mjs +32 -0
- package/dist/list-DJN-OvTZ.mjs +52 -0
- package/dist/list-DQj-QJAs.mjs +40 -0
- package/dist/list-Di529OJD.mjs +55 -0
- package/dist/{list-C4Ajrw8f.mjs → list-DlKzgnqo.mjs} +6 -3
- package/dist/list-GFfR9SuT.mjs +32 -0
- package/dist/{list-CWt3fqrZ.mjs → list-iFVEdi2J.mjs} +5 -3
- package/dist/{login-C9WTwNn6.mjs → login-DxgkosGx.mjs} +30 -9
- package/dist/{logout-oLszGCOg.mjs → logout-BlVwqBog.mjs} +7 -6
- package/dist/logs-CudNEkT4.mjs +58 -0
- package/dist/{manifest-CAdjQYH8.mjs → manifest-Dv5B9Blc.mjs} +3 -7
- package/dist/measure-BEQfnLdN.mjs +67 -0
- package/dist/measure-C7SbdYQk.mjs +19 -0
- package/dist/metadata-B2Td415K.mjs +38 -0
- package/dist/metadata-BTJAFVvZ.mjs +37 -0
- package/dist/{package-BGfw4ZWJ.mjs → package-DV6Asqim.mjs} +7 -1
- package/dist/paginate-CTSfuYiF.mjs +49 -0
- package/dist/parse-id-B38zTlYs.mjs +12 -0
- package/dist/parse-ref-DGvh4aDn.mjs +17 -0
- package/dist/parse-schemas-Ds-cVE-O.mjs +12 -0
- package/dist/{poll-ILanYysl.mjs → poll-Bh6oAifO.mjs} +2 -1
- package/dist/{poll-task-DbpsiQhl.mjs → poll-task-vPwV31Fs.mjs} +8 -7
- package/dist/predicates-DiIiS3k7.mjs +153 -0
- package/dist/preflight-DxJb-hUV.mjs +91 -0
- package/dist/{prompt-DpT8yAVy.mjs → prompt-Bf3DQ-qE.mjs} +1 -1
- package/dist/provision-B-I0zuDe.mjs +77 -0
- package/dist/ps-BmYQYC7t.mjs +10 -0
- package/dist/ps-CaiOFCv2.mjs +78 -0
- package/dist/query-BtF1yWZZ.mjs +90 -0
- package/dist/{query-PihYi-UZ.mjs → query-jmfqaXRP.mjs} +38 -13
- package/dist/remove-C2iv0g03.mjs +98 -0
- package/dist/remove-collection-DhZghaZy.mjs +38 -0
- package/dist/{remove-B2hVYn1v.mjs → remove-xskleeru.mjs} +6 -5
- package/dist/render-DXv-D6fU.mjs +182 -0
- package/dist/rescan-values-DW6u90ep.mjs +43 -0
- package/dist/revision-message-flag-CWQbKhdl.mjs +11 -0
- package/dist/{run-C2so6Qp6.mjs → run-DxVzhcF3.mjs} +27 -36
- package/dist/runs-BOHk1XnM.mjs +54 -0
- package/dist/{runtime-C9CEZhcn.mjs → runtime-cwBS8wwK.mjs} +428 -442
- package/dist/schema-tables-CcFbY_jN.mjs +45 -0
- package/dist/schemas-DZmv_V62.mjs +47 -0
- package/dist/{search-CopOytXY.mjs → search-CYMuc7Fg.mjs} +6 -19
- package/dist/segment-BMrUBz94.mjs +70 -0
- package/dist/segment-Df4pfjco.mjs +19 -0
- package/dist/{set-BcF7M1GQ.mjs → set-B_rrVwU4.mjs} +6 -4
- package/dist/{set-CbibegpA.mjs → set-CbGfQ7Ye.mjs} +8 -6
- package/dist/{setting-U3NtBMFo.mjs → setting-DqZY9NXP.mjs} +3 -3
- package/dist/setup-DxmcAorA.mjs +71 -0
- package/dist/snippet-CwSHjQyn.mjs +19 -0
- package/dist/snippet-Dw0Sjzkr.mjs +64 -0
- package/dist/start-Cn0epTks.mjs +380 -0
- package/dist/{stash-DOBbYozC.mjs → stash-BFZIl9F4.mjs} +9 -7
- package/dist/{status-Buf1ZbNR.mjs → status-BjCeJNLp.mjs} +10 -8
- package/dist/{status-CUcs8XBH.mjs → status-FDIDmqvM.mjs} +4 -2
- package/dist/{status-D1F5XHae.mjs → status-UALK3OJl.mjs} +4 -2
- package/dist/stop-DUwrDWw8.mjs +81 -0
- package/dist/summary-CS4UGiFJ.mjs +41 -0
- package/dist/sync-schema-IrHdJxmX.mjs +43 -0
- package/dist/{table-Cfk7oSvw.mjs → table-B-PYcgGb.mjs} +22 -9
- package/dist/table-Cdr5bKp1.mjs +19 -0
- package/dist/transform-CeZusR_w.mjs +24 -0
- package/dist/{transform-B5uRpg1G.mjs → transform-IEX4Mx3X.mjs} +56 -2
- package/dist/transform-job-BOn9-CGa.mjs +19 -0
- package/dist/{transform-job-C7QXWTVE.mjs → transform-job-Csr86muI.mjs} +7 -0
- package/dist/translate-B__zbDKm.mjs +111 -0
- package/dist/tree-Mh0uQ_Wy.mjs +32 -0
- package/dist/update-1Di9hbPo.mjs +56 -0
- package/dist/update-B5_pp6Jj.mjs +56 -0
- package/dist/update-B9DBMo30.mjs +52 -0
- package/dist/update-BfBsM_y1.mjs +56 -0
- package/dist/update-Bw0WZix_.mjs +73 -0
- package/dist/update-Cp1789qq.mjs +52 -0
- package/dist/update-D2VI_5cy.mjs +57 -0
- package/dist/update-D8GwQTcL.mjs +59 -0
- package/dist/{update-CL8tRbxr.mjs → update-Masp5WeT.mjs} +9 -7
- package/dist/update-dashcard-CNiQw1MD.mjs +71 -0
- package/dist/update-j9vgemKR.mjs +51 -0
- package/dist/url-GFM76VIK.mjs +54 -0
- package/dist/uuid-Uif0lNk8.mjs +47 -0
- package/dist/validate-DCYx6jdL.mjs +1496 -0
- package/dist/validate-query-B07oGG4K.mjs +37 -0
- package/dist/values-DrwNHUAI.mjs +36 -0
- package/dist/{wait-Bugr9eXD.mjs → wait-BoKk8CJy.mjs} +10 -8
- package/dist/wait-DO7tS7NI.mjs +19 -0
- package/dist/wait-flags-CjX2sEGm.mjs +35 -0
- package/dist/workspace-CyEX40D-.mjs +24 -0
- package/dist/workspace-DVuqKJGG.mjs +72 -0
- package/dist/workspace-credentials-B6BL-X0d.mjs +139 -0
- package/package.json +7 -1
- package/dist/auth-BF7IjZIH.mjs +0 -18
- package/dist/card-_Ta7zdYe.mjs +0 -19
- package/dist/create-CI2Cunq5.mjs +0 -38
- package/dist/create-DdbU3TLX.mjs +0 -42
- package/dist/database-PA9Goi25.mjs +0 -33
- package/dist/db-DMghzgb6.mjs +0 -17
- package/dist/field-C8IVs6rp.mjs +0 -76
- package/dist/field-DaYo_90x.mjs +0 -13
- package/dist/get-Cwpj7lDe.mjs +0 -35
- package/dist/get-Dh_acl8q.mjs +0 -34
- package/dist/is-dirty-DpKn9HJp.mjs +0 -8
- package/dist/list-CBSBHtK-.mjs +0 -38
- package/dist/parse-id-BhmmfyCP.mjs +0 -14
- package/dist/sync-BPyGXfUk.mjs +0 -26
- package/dist/table-D7nJt7JO.mjs +0 -16
- package/dist/transform-UbyewMxY.mjs +0 -21
- package/dist/transform-job-CrYkr-Ma.mjs +0 -19
- package/dist/update-DU2oU2j-.mjs +0 -49
- /package/dist/{body-flags-BUA9XV1u.mjs → body-flags-BK7J6Daz.mjs} +0 -0
- /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
|
|
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 {
|
|
2
|
-
import { DEFAULT_INTERVAL_MS, DEFAULT_TIMEOUT_MS, pollUntil } from "./poll-
|
|
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/
|
|
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
|
|
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 };
|
|
@@ -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 };
|