@kweaver-ai/kweaver-sdk 0.4.10 → 0.4.12

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.
@@ -4,19 +4,24 @@ export async function runAuthCommand(args) {
4
4
  const target = args[0];
5
5
  const rest = args.slice(1);
6
6
  if (!target || target === "--help" || target === "-h") {
7
- console.log(`kweaver auth login <url> [--alias <name>] [-u user] [-p pass] [--playwright]
8
- kweaver auth <url> Login (shorthand; same options as login)
9
- kweaver auth status [url|alias]
10
- kweaver auth list List saved platforms
11
- kweaver auth use <url|alias> Switch active platform
12
- kweaver auth logout [url|alias] Logout (clear local token)
13
- kweaver auth delete <url|alias> Delete saved credentials
7
+ console.log(`kweaver auth login <url> [options] Login to a platform (browser OAuth2 by default)
8
+ kweaver auth <url> Login (shorthand; same options as login)
9
+ kweaver auth status [url|alias] Show current auth status
10
+ kweaver auth list List saved platforms
11
+ kweaver auth use <url|alias> Switch active platform
12
+ kweaver auth logout [url|alias] Logout (clear local token)
13
+ kweaver auth delete <url|alias> Delete saved credentials
14
14
 
15
- Login options (browser OAuth2 by default; use -u/-p for headless Playwright):
16
- --alias <name> Short name for this platform (use with auth use / status / logout)
17
- -u, --username Username (with -p triggers Playwright login)
18
- -p, --password Password
19
- --playwright Force browser (Playwright) login even without -u/-p`);
15
+ Login options:
16
+ --alias <name> Save platform with a short alias (use with use / status / logout)
17
+ --client-id <id> Use an existing OAuth2 client ID instead of registering a new one.
18
+ Use the platform's web app client ID to get the same permissions
19
+ as the browser. Find it in DevTools: /oauth2/auth?client_id=<id>
20
+ --client-secret <s> Client secret (omit for public/PKCE clients)
21
+ -u, --username Username (with -p triggers Playwright headless login)
22
+ -p, --password Password
23
+ --playwright Force Playwright browser login even without -u/-p
24
+ --insecure, -k Skip TLS certificate verification (self-signed / dev HTTPS only)`);
20
25
  return 0;
21
26
  }
22
27
  if (target === "login") {
@@ -38,21 +43,33 @@ Login options (browser OAuth2 by default; use -u/-p for headless Playwright):
38
43
  const username = readOption(args, "--username") ?? readOption(args, "-u");
39
44
  const password = readOption(args, "--password") ?? readOption(args, "-p");
40
45
  const usePlaywright = args.includes("--playwright");
46
+ const clientId = readOption(args, "--client-id");
47
+ const clientSecret = readOption(args, "--client-secret");
48
+ const tlsInsecure = args.includes("--insecure") || args.includes("-k");
41
49
  let token;
42
50
  if (username && password) {
43
51
  // Headless Playwright login with credentials
44
52
  console.log("Logging in (headless)...");
45
- token = await playwrightLogin(normalizedTarget, { username, password });
53
+ token = await playwrightLogin(normalizedTarget, { username, password, tlsInsecure });
46
54
  }
47
55
  else if (usePlaywright) {
48
56
  // Explicit Playwright fallback
49
57
  console.log("Opening browser for login (Playwright)...");
50
- token = await playwrightLogin(normalizedTarget);
58
+ token = await playwrightLogin(normalizedTarget, { tlsInsecure });
51
59
  }
52
60
  else {
53
61
  // Default: OAuth2 authorization code flow (supports refresh_token)
54
- console.log("Opening browser for OAuth2 login...");
55
- token = await oauth2Login(normalizedTarget);
62
+ if (clientId) {
63
+ console.log(`Opening browser for OAuth2 login (client: ${clientId})...`);
64
+ }
65
+ else {
66
+ console.log("Opening browser for OAuth2 login...");
67
+ }
68
+ token = await oauth2Login(normalizedTarget, {
69
+ clientId: clientId ?? undefined,
70
+ clientSecret: clientSecret ?? undefined,
71
+ tlsInsecure,
72
+ });
56
73
  }
57
74
  if (alias) {
58
75
  setPlatformAlias(normalizedTarget, alias);
@@ -106,6 +123,9 @@ Login options (browser OAuth2 by default; use -u/-p for headless Playwright):
106
123
  `Token present: yes`,
107
124
  ];
108
125
  lines.push(`Refresh token: ${token.refreshToken ? "yes (auto-refresh enabled)" : "no"}`);
126
+ if (token.tlsInsecure) {
127
+ lines.push(`TLS: certificate verification disabled (saved; dev only)`);
128
+ }
109
129
  if (token.expiresAt) {
110
130
  const expiry = new Date(token.expiresAt);
111
131
  const remainingMs = expiry.getTime() - Date.now();
@@ -8,11 +8,12 @@ import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/
8
8
  import { listKnowledgeNetworks, getKnowledgeNetwork, createKnowledgeNetwork, updateKnowledgeNetwork, deleteKnowledgeNetwork, listObjectTypes, listRelationTypes, listActionTypes, getObjectType, createObjectTypes, updateObjectType, deleteObjectTypes, getRelationType, createRelationTypes, updateRelationType, deleteRelationTypes, buildKnowledgeNetwork, getBuildStatus, } from "../api/knowledge-networks.js";
9
9
  import { objectTypeQuery, objectTypeProperties, subgraph, actionTypeQuery, actionTypeExecute, actionExecutionGet, actionLogsList, actionLogGet, actionLogCancel, } from "../api/ontology-query.js";
10
10
  import { semanticSearch } from "../api/semantic-search.js";
11
- import { listTablesWithColumns } from "../api/datasources.js";
12
- import { createDataView } from "../api/dataviews.js";
11
+ import { listTablesWithColumns, scanMetadata, getDatasource } from "../api/datasources.js";
12
+ import { createDataView, findDataView } from "../api/dataviews.js"; // used by runKnCreateFromDsCommand
13
13
  import { downloadBkn, uploadBkn } from "../api/bkn-backend.js";
14
14
  import { formatCallOutput } from "./call.js";
15
15
  import { resolveBusinessDomain } from "../config/store.js";
16
+ import { runDsImportCsv } from "./ds.js";
16
17
  export function formatSimpleKnList(text, pretty, includeDetail = false) {
17
18
  const parsed = JSON.parse(text);
18
19
  const entries = Array.isArray(parsed.entries) ? parsed.entries : [];
@@ -600,6 +601,8 @@ Subcommands:
600
601
  get <kn-id> [options] Get knowledge network detail (use --stats or --export)
601
602
  create [options] Create a knowledge network (empty or from --body-file)
602
603
  create-from-ds <ds-id> --name X [--tables a,b] [--build] Create KN from datasource
604
+ create-from-csv <ds-id> --files <glob> --name X [--table-prefix P] [--build]
605
+ Import CSVs then create knowledge network
603
606
  update <kn-id> [options] Update a knowledge network
604
607
  delete <kn-id> Delete a knowledge network
605
608
  build <kn-id> [--wait|--no-wait] [--timeout n] Trigger full build
@@ -646,6 +649,8 @@ export async function runKnCommand(args) {
646
649
  return runKnCreateCommand(rest);
647
650
  if (subcommand === "create-from-ds")
648
651
  return runKnCreateFromDsCommand(rest);
652
+ if (subcommand === "create-from-csv")
653
+ return runKnCreateFromCsvCommand(rest);
649
654
  if (subcommand === "update")
650
655
  return runKnUpdateCommand(rest);
651
656
  if (subcommand === "delete")
@@ -1074,20 +1079,18 @@ export function parseKnActionTypeExecuteArgs(args) {
1074
1079
  timeout,
1075
1080
  };
1076
1081
  }
1077
- const PK_CANDIDATES = new Set(["id", "pk", "key"]);
1078
- const PK_TYPES = new Set(["integer", "unsigned integer", "string", "varchar", "bigint", "int"]);
1079
1082
  const DISPLAY_HINTS = ["name", "title", "label", "display_name", "description"];
1080
- function detectPrimaryKey(table) {
1081
- for (const col of table.columns) {
1082
- if (PK_CANDIDATES.has(col.name.toLowerCase()) && PK_TYPES.has(col.type.toLowerCase())) {
1083
- return col.name;
1084
- }
1085
- }
1086
- for (const col of table.columns) {
1087
- if (PK_TYPES.has(col.type.toLowerCase())) {
1088
- return col.name;
1083
+ /** Detect primary key: first column (left-to-right) with all unique values in the sample. */
1084
+ function detectPrimaryKey(table, rows) {
1085
+ if (rows && rows.length > 0) {
1086
+ for (const col of table.columns) {
1087
+ const values = rows.map((r) => r[col.name]);
1088
+ const unique = new Set(values);
1089
+ if (unique.size === rows.length)
1090
+ return col.name;
1089
1091
  }
1090
1092
  }
1093
+ // Fallback: first column
1091
1094
  return table.columns[0]?.name ?? "id";
1092
1095
  }
1093
1096
  function detectDisplayKey(table, primaryKey) {
@@ -2141,7 +2144,25 @@ function parseKnCreateFromDsArgs(args) {
2141
2144
  businessDomain = resolveBusinessDomain();
2142
2145
  return { dsId, name, tables, build, timeout, businessDomain, pretty };
2143
2146
  }
2144
- async function runKnCreateFromDsCommand(args) {
2147
+ /** Sanitize a table name into a BKN-safe ID (alphanumeric + underscore). */
2148
+ function sanitizeBknId(name) {
2149
+ return name.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^(\d)/, "_$1");
2150
+ }
2151
+ /** Generate a BKN ObjectType YAML markdown file for a table. */
2152
+ function generateObjectTypeBkn(tableName, dvId, pk, dk, columns) {
2153
+ const safeId = sanitizeBknId(tableName);
2154
+ const header = `## ObjectType: ${safeId}\n\n**${tableName}**\n`;
2155
+ const dsTable = `### Data Source\n\n| Type | ID | Name |\n|------|-----|------|\n| data_view | ${dvId} | ${tableName} |\n`;
2156
+ const dpHeader = `### Data Properties\n\n| Property | Display Name | Type | Primary Key | Display Key |\n|----------|-------------|------|-------------|-------------|\n`;
2157
+ const dpRows = columns.map((c) => {
2158
+ const isPk = c.name === pk ? "yes" : "no";
2159
+ const isDk = c.name === dk ? "yes" : "no";
2160
+ return `| ${c.name} | ${c.name} | string | ${isPk} | ${isDk} |`;
2161
+ }).join("\n");
2162
+ const frontmatter = `---\ntype: object_type\nid: ${safeId}\nname: ${tableName}\n---\n\n`;
2163
+ return `${frontmatter}${header}\n${dsTable}\n${dpHeader}${dpRows}\n`;
2164
+ }
2165
+ async function runKnCreateFromDsCommand(args, sampleRows) {
2145
2166
  let options;
2146
2167
  try {
2147
2168
  options = parseKnCreateFromDsArgs(args);
@@ -2170,17 +2191,28 @@ async function runKnCreateFromDsCommand(args) {
2170
2191
  console.error("No tables available");
2171
2192
  return 1;
2172
2193
  }
2194
+ // Phase 1: Create DataViews for each table
2195
+ console.error(`Creating data views for ${targetTables.length} table(s) ...`);
2173
2196
  const viewMap = {};
2174
2197
  for (const t of targetTables) {
2175
- const dvId = await createDataView({
2198
+ const found = await findDataView({
2176
2199
  ...base,
2177
2200
  name: t.name,
2178
2201
  datasourceId: options.dsId,
2179
- table: t.name,
2180
- fields: t.columns.map((c) => ({ name: c.name, type: c.type })),
2202
+ exact: true,
2203
+ wait: true,
2181
2204
  });
2205
+ const dvId = found[0]?.id ??
2206
+ (await createDataView({
2207
+ ...base,
2208
+ name: t.name,
2209
+ datasourceId: options.dsId,
2210
+ table: t.name,
2211
+ fields: t.columns.map((c) => ({ name: c.name, type: c.type })),
2212
+ }));
2182
2213
  viewMap[t.name] = dvId;
2183
2214
  }
2215
+ // Phase 2: Create the KN record
2184
2216
  const knBody = JSON.stringify({
2185
2217
  name: options.name,
2186
2218
  branch: "main",
@@ -2193,20 +2225,25 @@ async function runKnCreateFromDsCommand(args) {
2193
2225
  const knParsed = JSON.parse(knResponse);
2194
2226
  const knItem = Array.isArray(knParsed) ? knParsed[0] : knParsed;
2195
2227
  const knId = String(knItem?.id ?? "");
2228
+ console.error(`Knowledge network created: ${knId}`);
2229
+ // Phase 3: Create object types via REST API
2230
+ console.error(`Creating ${targetTables.length} object type(s) ...`);
2196
2231
  const otResults = [];
2197
2232
  for (const t of targetTables) {
2198
- const pk = detectPrimaryKey(t);
2233
+ const pk = detectPrimaryKey(t, sampleRows?.[t.name]);
2199
2234
  const dk = detectDisplayKey(t, pk);
2235
+ const uniqueProps = [pk, dk].filter((x, i, a) => a.indexOf(x) === i);
2200
2236
  const entry = {
2201
2237
  branch: "main",
2202
2238
  name: t.name,
2203
2239
  data_source: { type: "data_view", id: viewMap[t.name] },
2204
2240
  primary_keys: [pk],
2205
2241
  display_key: dk,
2206
- data_properties: [pk, dk].filter((x, i, a) => a.indexOf(x) === i).map((n) => ({
2207
- name: n,
2208
- display_name: n,
2242
+ data_properties: t.columns.map((c) => ({
2243
+ name: c.name,
2244
+ display_name: c.name,
2209
2245
  type: "string",
2246
+ mapped_field: { name: c.name, type: c.type || "varchar" },
2210
2247
  })),
2211
2248
  };
2212
2249
  const otBody = JSON.stringify({ entries: [entry] });
@@ -2222,6 +2259,16 @@ async function runKnCreateFromDsCommand(args) {
2222
2259
  id: otItem?.id ?? "",
2223
2260
  field_count: t.columns.length,
2224
2261
  });
2262
+ console.error(` Created: ${t.name} (${t.columns.length} fields, pk=${pk}, dk=${dk})`);
2263
+ }
2264
+ if (otResults.length === 0) {
2265
+ const errorOutput = {
2266
+ kn_id: knId,
2267
+ kn_name: options.name,
2268
+ error: "No object types were created",
2269
+ };
2270
+ console.log(JSON.stringify(errorOutput, null, options.pretty ? 2 : 0));
2271
+ return 1;
2225
2272
  }
2226
2273
  let statusStr = "skipped";
2227
2274
  if (options.build) {
@@ -2749,3 +2796,149 @@ async function runKnSearchCommand(args) {
2749
2796
  return 1;
2750
2797
  }
2751
2798
  }
2799
+ const KN_CREATE_FROM_CSV_HELP = `kweaver bkn create-from-csv <ds-id> --files <glob> --name X [options]
2800
+
2801
+ Import CSV files into datasource, then create a knowledge network.
2802
+
2803
+ Options:
2804
+ --files <s> CSV file paths (comma-separated or glob, required)
2805
+ --name <s> Knowledge network name (required)
2806
+ --table-prefix <s> Table name prefix (default: none)
2807
+ --batch-size <n> Rows per batch (default: 500)
2808
+ --tables <a,b> Tables to include in KN (default: all imported)
2809
+ --build (default) Build after creation
2810
+ --no-build Skip build
2811
+ --timeout <n> Build timeout in seconds (default: 300)
2812
+ -bd, --biz-domain Business domain (default: bd_public)`;
2813
+ function parseKnCreateFromCsvArgs(args) {
2814
+ let dsId = "";
2815
+ let files = "";
2816
+ let name = "";
2817
+ let tablePrefix = "";
2818
+ let batchSize = 500;
2819
+ let tablesStr = "";
2820
+ let build = true;
2821
+ let timeout = 300;
2822
+ let businessDomain = "";
2823
+ for (let i = 0; i < args.length; i += 1) {
2824
+ const arg = args[i];
2825
+ if (arg === "--help" || arg === "-h")
2826
+ throw new Error("help");
2827
+ if (arg === "--files" && args[i + 1]) {
2828
+ files = args[++i];
2829
+ continue;
2830
+ }
2831
+ if (arg === "--name" && args[i + 1]) {
2832
+ name = args[++i];
2833
+ continue;
2834
+ }
2835
+ if (arg === "--table-prefix" && args[i + 1]) {
2836
+ tablePrefix = args[++i];
2837
+ continue;
2838
+ }
2839
+ if (arg === "--batch-size" && args[i + 1]) {
2840
+ batchSize = parseInt(args[++i], 10);
2841
+ if (Number.isNaN(batchSize) || batchSize < 1)
2842
+ batchSize = 500;
2843
+ continue;
2844
+ }
2845
+ if (arg === "--tables" && args[i + 1]) {
2846
+ tablesStr = args[++i];
2847
+ continue;
2848
+ }
2849
+ if (arg === "--build") {
2850
+ build = true;
2851
+ continue;
2852
+ }
2853
+ if (arg === "--no-build") {
2854
+ build = false;
2855
+ continue;
2856
+ }
2857
+ if (arg === "--timeout" && args[i + 1]) {
2858
+ timeout = parseInt(args[++i], 10);
2859
+ if (Number.isNaN(timeout) || timeout < 1)
2860
+ timeout = 300;
2861
+ continue;
2862
+ }
2863
+ if ((arg === "-bd" || arg === "--biz-domain") && args[i + 1]) {
2864
+ businessDomain = args[++i];
2865
+ continue;
2866
+ }
2867
+ if (!arg.startsWith("-") && !dsId) {
2868
+ dsId = arg;
2869
+ }
2870
+ }
2871
+ const tables = tablesStr ? tablesStr.split(",").map((s) => s.trim()).filter(Boolean) : [];
2872
+ if (!dsId || !files || !name) {
2873
+ throw new Error("Usage: kweaver bkn create-from-csv <ds-id> --files <glob> --name X [options]");
2874
+ }
2875
+ if (!businessDomain)
2876
+ businessDomain = resolveBusinessDomain();
2877
+ return { dsId, files, name, tablePrefix, batchSize, tables, build, timeout, businessDomain };
2878
+ }
2879
+ async function runKnCreateFromCsvCommand(args) {
2880
+ let options;
2881
+ try {
2882
+ options = parseKnCreateFromCsvArgs(args);
2883
+ }
2884
+ catch (error) {
2885
+ if (error instanceof Error && error.message === "help") {
2886
+ console.log(KN_CREATE_FROM_CSV_HELP);
2887
+ return 0;
2888
+ }
2889
+ console.error(formatHttpError(error));
2890
+ return 1;
2891
+ }
2892
+ // Phase 1: Import CSVs
2893
+ console.error("Phase 1: Importing CSVs ...");
2894
+ const importArgs = [
2895
+ options.dsId,
2896
+ "--files", options.files,
2897
+ "--table-prefix", options.tablePrefix,
2898
+ "--batch-size", String(options.batchSize),
2899
+ "-bd", options.businessDomain,
2900
+ ];
2901
+ const importResult = await runDsImportCsv(importArgs);
2902
+ if (importResult.code !== 0) {
2903
+ console.error("CSV import failed — aborting KN creation");
2904
+ return importResult.code;
2905
+ }
2906
+ // Phase 1.5: Scan datasource metadata so platform discovers newly imported tables
2907
+ console.error("Scanning datasource metadata ...");
2908
+ try {
2909
+ const token = await ensureValidToken();
2910
+ const dsBody = await getDatasource({
2911
+ baseUrl: token.baseUrl,
2912
+ accessToken: token.accessToken,
2913
+ id: options.dsId,
2914
+ businessDomain: options.businessDomain,
2915
+ });
2916
+ const dsParsed = JSON.parse(dsBody);
2917
+ await scanMetadata({
2918
+ baseUrl: token.baseUrl,
2919
+ accessToken: token.accessToken,
2920
+ id: options.dsId,
2921
+ dsType: dsParsed.type ?? "mysql",
2922
+ businessDomain: options.businessDomain,
2923
+ });
2924
+ }
2925
+ catch (err) {
2926
+ console.error(`Scan warning (continuing): ${String(err)}`);
2927
+ }
2928
+ // Phase 2: Create KN from datasource
2929
+ console.error("Phase 2: Creating knowledge network ...");
2930
+ const tableNames = options.tables.length > 0 ? options.tables : importResult.tables;
2931
+ if (tableNames.length === 0) {
2932
+ console.error("No tables available for KN creation — aborting");
2933
+ return 1;
2934
+ }
2935
+ const knArgs = [
2936
+ options.dsId,
2937
+ "--name", options.name,
2938
+ "--tables", tableNames.join(","),
2939
+ options.build ? "--build" : "--no-build",
2940
+ "--timeout", String(options.timeout),
2941
+ "-bd", options.businessDomain,
2942
+ ];
2943
+ return runKnCreateFromDsCommand(knArgs, importResult.sampleRows);
2944
+ }
@@ -0,0 +1 @@
1
+ export declare function runDataviewCommand(args: string[]): Promise<number>;
@@ -0,0 +1,244 @@
1
+ import { createInterface } from "node:readline";
2
+ import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/oauth.js";
3
+ import { deleteDataView, findDataView, getDataView, listDataViews, } from "../api/dataviews.js";
4
+ import { formatCallOutput } from "./call.js";
5
+ import { resolveBusinessDomain } from "../config/store.js";
6
+ function confirmYes(prompt) {
7
+ return new Promise((resolve) => {
8
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
9
+ rl.question(`${prompt} [y/N] `, (answer) => {
10
+ rl.close();
11
+ const trimmed = answer.trim().toLowerCase();
12
+ resolve(trimmed === "y" || trimmed === "yes");
13
+ });
14
+ });
15
+ }
16
+ export async function runDataviewCommand(args) {
17
+ const [subcommand, ...rest] = args;
18
+ if (!subcommand || subcommand === "--help" || subcommand === "-h") {
19
+ console.log(`kweaver dataview
20
+
21
+ Subcommands:
22
+ list [--datasource-id <id>] [--type <atomic|custom>] [--limit <n>] [-bd value] [--pretty]
23
+ find --name <name> [--exact] [--datasource-id <id>] [--wait] [--no-wait] [--timeout <ms>] [-bd value] [--pretty]
24
+ get <id> [-bd value] [--pretty]
25
+ delete <id> [-y] [-bd value]
26
+
27
+ list — list all data views (no keyword search)
28
+ find — search by name; default fuzzy, --exact for strict match, --wait to poll`);
29
+ return 0;
30
+ }
31
+ const dispatch = () => {
32
+ if (subcommand === "list")
33
+ return runDataviewListCommand(rest);
34
+ if (subcommand === "find")
35
+ return runDataviewFindCommand(rest);
36
+ if (subcommand === "get")
37
+ return runDataviewGetCommand(rest);
38
+ if (subcommand === "delete")
39
+ return runDataviewDeleteCommand(rest);
40
+ return Promise.resolve(-1);
41
+ };
42
+ try {
43
+ return await with401RefreshRetry(async () => {
44
+ const code = await dispatch();
45
+ if (code === -1) {
46
+ console.error(`Unknown dataview subcommand: ${subcommand}`);
47
+ return 1;
48
+ }
49
+ return code;
50
+ });
51
+ }
52
+ catch (error) {
53
+ console.error(formatHttpError(error));
54
+ return 1;
55
+ }
56
+ }
57
+ function parseDataviewCommonArgs(args) {
58
+ let businessDomain = "";
59
+ let pretty = true;
60
+ for (let i = 0; i < args.length; i += 1) {
61
+ const arg = args[i];
62
+ if ((arg === "-bd" || arg === "--biz-domain") && args[i + 1]) {
63
+ businessDomain = args[++i];
64
+ continue;
65
+ }
66
+ if (arg === "--pretty") {
67
+ pretty = true;
68
+ continue;
69
+ }
70
+ }
71
+ if (!businessDomain)
72
+ businessDomain = resolveBusinessDomain();
73
+ return { businessDomain, pretty };
74
+ }
75
+ async function runDataviewListCommand(args) {
76
+ let datasourceId;
77
+ let type;
78
+ let limit;
79
+ const { businessDomain, pretty } = parseDataviewCommonArgs(args);
80
+ for (let i = 0; i < args.length; i += 1) {
81
+ const arg = args[i];
82
+ if (arg === "-bd" || arg === "--biz-domain") {
83
+ i += 1;
84
+ continue;
85
+ }
86
+ if (arg === "--pretty")
87
+ continue;
88
+ if (arg === "--datasource-id" && args[i + 1]) {
89
+ datasourceId = args[++i];
90
+ continue;
91
+ }
92
+ if (arg === "--type" && args[i + 1]) {
93
+ type = args[++i];
94
+ continue;
95
+ }
96
+ if (arg === "--limit" && args[i + 1]) {
97
+ const n = Number.parseInt(args[++i], 10);
98
+ if (!Number.isNaN(n))
99
+ limit = n;
100
+ continue;
101
+ }
102
+ }
103
+ const token = await ensureValidToken();
104
+ const views = await listDataViews({
105
+ baseUrl: token.baseUrl,
106
+ accessToken: token.accessToken,
107
+ businessDomain,
108
+ datasourceId,
109
+ type,
110
+ limit,
111
+ });
112
+ console.log(formatCallOutput(JSON.stringify(views), pretty));
113
+ return 0;
114
+ }
115
+ async function runDataviewFindCommand(args) {
116
+ let datasourceId;
117
+ let name;
118
+ let exact = false;
119
+ let wait = false;
120
+ let timeoutMs = 30_000;
121
+ const { businessDomain, pretty } = parseDataviewCommonArgs(args);
122
+ for (let i = 0; i < args.length; i += 1) {
123
+ const arg = args[i];
124
+ if (arg === "-bd" || arg === "--biz-domain") {
125
+ i += 1;
126
+ continue;
127
+ }
128
+ if (arg === "--pretty")
129
+ continue;
130
+ if (arg === "--datasource-id" && args[i + 1]) {
131
+ datasourceId = args[++i];
132
+ continue;
133
+ }
134
+ if (arg === "--name" && args[i + 1]) {
135
+ name = args[++i];
136
+ continue;
137
+ }
138
+ if (arg === "--exact") {
139
+ exact = true;
140
+ continue;
141
+ }
142
+ if (arg === "--wait") {
143
+ wait = true;
144
+ continue;
145
+ }
146
+ if (arg === "--no-wait") {
147
+ wait = false;
148
+ continue;
149
+ }
150
+ if (arg === "--timeout" && args[i + 1]) {
151
+ timeoutMs = Number(args[++i]);
152
+ if (Number.isNaN(timeoutMs) || timeoutMs < 0) {
153
+ console.error("Invalid --timeout value");
154
+ return 1;
155
+ }
156
+ continue;
157
+ }
158
+ }
159
+ if (!name) {
160
+ console.error("Usage: kweaver dataview find --name <name> [--exact] [--datasource-id <id>] [--wait] [--timeout <ms>] [-bd value] [--pretty]");
161
+ return 1;
162
+ }
163
+ const token = await ensureValidToken();
164
+ const views = await findDataView({
165
+ baseUrl: token.baseUrl,
166
+ accessToken: token.accessToken,
167
+ businessDomain,
168
+ name,
169
+ datasourceId,
170
+ exact,
171
+ wait,
172
+ timeoutMs,
173
+ });
174
+ console.log(formatCallOutput(JSON.stringify(views), pretty));
175
+ return 0;
176
+ }
177
+ async function runDataviewGetCommand(args) {
178
+ const { businessDomain, pretty } = parseDataviewCommonArgs(args);
179
+ let id = "";
180
+ for (let i = 0; i < args.length; i += 1) {
181
+ const arg = args[i];
182
+ if (arg === "-bd" || arg === "--biz-domain") {
183
+ i += 1;
184
+ continue;
185
+ }
186
+ if (arg === "--pretty")
187
+ continue;
188
+ if (!arg.startsWith("-")) {
189
+ id = arg;
190
+ break;
191
+ }
192
+ }
193
+ if (!id) {
194
+ console.error("Usage: kweaver dataview get <id> [-bd value] [--pretty]");
195
+ return 1;
196
+ }
197
+ const token = await ensureValidToken();
198
+ const view = await getDataView({
199
+ baseUrl: token.baseUrl,
200
+ accessToken: token.accessToken,
201
+ businessDomain,
202
+ id,
203
+ });
204
+ console.log(formatCallOutput(JSON.stringify(view), pretty));
205
+ return 0;
206
+ }
207
+ async function runDataviewDeleteCommand(args) {
208
+ let id = "";
209
+ let yes = false;
210
+ let businessDomain = "";
211
+ for (let i = 0; i < args.length; i += 1) {
212
+ const arg = args[i];
213
+ if (arg === "--yes" || arg === "-y")
214
+ yes = true;
215
+ else if ((arg === "-bd" || arg === "--biz-domain") && args[i + 1]) {
216
+ businessDomain = args[++i];
217
+ continue;
218
+ }
219
+ else if (!arg.startsWith("-"))
220
+ id = arg;
221
+ }
222
+ if (!businessDomain)
223
+ businessDomain = resolveBusinessDomain();
224
+ if (!id) {
225
+ console.error("Usage: kweaver dataview delete <id> [-y] [-bd value]");
226
+ return 1;
227
+ }
228
+ if (!yes) {
229
+ const confirmed = await confirmYes("Are you sure you want to delete this data view?");
230
+ if (!confirmed) {
231
+ console.error("Aborted.");
232
+ return 1;
233
+ }
234
+ }
235
+ const token = await ensureValidToken();
236
+ await deleteDataView({
237
+ baseUrl: token.baseUrl,
238
+ accessToken: token.accessToken,
239
+ businessDomain,
240
+ id,
241
+ });
242
+ console.error(`Deleted ${id}`);
243
+ return 0;
244
+ }
@@ -5,3 +5,19 @@ export declare function parseDsListArgs(args: string[]): {
5
5
  businessDomain: string;
6
6
  pretty: boolean;
7
7
  };
8
+ export declare function parseImportCsvArgs(args: string[]): {
9
+ datasourceId: string;
10
+ files: string;
11
+ tablePrefix: string;
12
+ batchSize: number;
13
+ businessDomain: string;
14
+ };
15
+ export declare function resolveFiles(pattern: string): Promise<string[]>;
16
+ export interface ImportCsvResult {
17
+ code: number;
18
+ tables: string[];
19
+ tableColumns: Record<string, string[]>;
20
+ sampleRows: Record<string, Array<Record<string, string | null>>>;
21
+ }
22
+ export declare function runDsImportCsv(args: string[]): Promise<ImportCsvResult>;
23
+ export declare function runDsImportCsvCommand(args: string[]): Promise<number>;