@yejiming/dsh-data-agent 0.0.11 → 0.0.13
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.en.md +70 -15
- package/README.md +70 -15
- package/conformance/dsh-ecosystem/baseline.json +59 -0
- package/conformance/dsh-ecosystem/dependencies.json +41 -0
- package/conformance/dsh-ecosystem/fixtures/host-degraded.fixture.json +12 -0
- package/conformance/dsh-ecosystem/fixtures/host-eligible.fixture.json +13 -0
- package/conformance/dsh-ecosystem/fixtures/host-rejected.fixture.json +12 -0
- package/conformance/dsh-ecosystem/fixtures/profiles/native-only/package.json +8 -0
- package/conformance/dsh-ecosystem/fixtures/profiles/native-plus-adapter/package.json +9 -0
- package/conformance/dsh-ecosystem/inventory.json +77 -0
- package/conformance/dsh-ecosystem/restrictions.json +20 -0
- package/dsh-plugin.json +67 -0
- package/lib/client.js +1352 -130
- package/lib/client.js.map +1 -1
- package/lib/{command-DuCpwVbl.js → command-utC5MHd9.js} +101 -60
- package/lib/command.js +1 -1
- package/lib/{connections-5sfdEDsG.js → connections-CHY4uB6z.js} +747 -65
- package/lib/defaults-Cngd8Tf8.js +131 -0
- package/lib/ecosystem.js +19 -0
- package/lib/index.js +40 -33
- package/lib/routes.js +5 -6
- package/lib/{tool-DVh61An-.js → tool-ZTOS4B33.js} +161 -177
- package/lib/tool.js +1 -1
- package/lib/types/analysis-html.d.ts +27 -0
- package/lib/types/analysis.d.ts +13 -1
- package/lib/types/client/DataAgentWorkbench.d.ts +1 -2
- package/lib/types/client/QueryResultTable.d.ts +13 -0
- package/lib/types/client/locales.d.ts +48 -0
- package/lib/types/client/persistence.d.ts +3 -1
- package/lib/types/client/query-export.d.ts +11 -0
- package/lib/types/client-discovery.d.ts +3 -4
- package/lib/types/clients.d.ts +14 -8
- package/lib/types/command.d.ts +2 -2
- package/lib/types/connections.d.ts +33 -4
- package/lib/types/database-types.d.ts +23 -0
- package/lib/types/defaults.d.ts +4 -0
- package/lib/types/ecosystem.d.ts +13 -0
- package/lib/types/index.d.ts +21 -16
- package/lib/types/presentation-text.d.ts +3 -0
- package/lib/types/query.d.ts +13 -11
- package/lib/types/sql.d.ts +9 -1
- package/lib/types/storage.d.ts +11 -1
- package/lib/types/structured-read.d.ts +2 -2
- package/lib/types/structured.d.ts +1 -1
- package/lib/types/tool.d.ts +5 -5
- package/lib/types/tui-connection-form.d.ts +10 -7
- package/package.json +66 -42
- package/preset/data-agent/agent.cordis.yml +9 -4
- package/lib/defaults-DP4RyRh1.js +0 -21
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//#region src/database-types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Browser-safe database type descriptors shared by every DSH surface.
|
|
4
|
+
* Keep this module dependency-free: server-only client/process details belong
|
|
5
|
+
* in the database adapters, not in Web or persistence bundles.
|
|
6
|
+
*/
|
|
7
|
+
const DATABASE_TYPES = [
|
|
8
|
+
"mysql",
|
|
9
|
+
"postgres",
|
|
10
|
+
"sqlite",
|
|
11
|
+
"oracle",
|
|
12
|
+
"hive",
|
|
13
|
+
"impala",
|
|
14
|
+
"clickhouse",
|
|
15
|
+
"doris",
|
|
16
|
+
"sqlserver"
|
|
17
|
+
];
|
|
18
|
+
const DATABASE_TYPE_DESCRIPTORS = {
|
|
19
|
+
mysql: {
|
|
20
|
+
type: "mysql",
|
|
21
|
+
label: "MySQL",
|
|
22
|
+
localeKey: "type.mysql",
|
|
23
|
+
defaultPort: 3306,
|
|
24
|
+
defaultUser: "root",
|
|
25
|
+
fileBased: false
|
|
26
|
+
},
|
|
27
|
+
postgres: {
|
|
28
|
+
type: "postgres",
|
|
29
|
+
label: "PostgreSQL",
|
|
30
|
+
localeKey: "type.postgres",
|
|
31
|
+
defaultPort: 5432,
|
|
32
|
+
defaultUser: "postgres",
|
|
33
|
+
fileBased: false
|
|
34
|
+
},
|
|
35
|
+
sqlite: {
|
|
36
|
+
type: "sqlite",
|
|
37
|
+
label: "SQLite",
|
|
38
|
+
localeKey: "type.sqlite",
|
|
39
|
+
defaultPort: 0,
|
|
40
|
+
defaultUser: "",
|
|
41
|
+
fileBased: true
|
|
42
|
+
},
|
|
43
|
+
oracle: {
|
|
44
|
+
type: "oracle",
|
|
45
|
+
label: "Oracle",
|
|
46
|
+
localeKey: "type.oracle",
|
|
47
|
+
defaultPort: 1521,
|
|
48
|
+
defaultUser: "",
|
|
49
|
+
fileBased: false
|
|
50
|
+
},
|
|
51
|
+
hive: {
|
|
52
|
+
type: "hive",
|
|
53
|
+
label: "Hive",
|
|
54
|
+
localeKey: "type.hive",
|
|
55
|
+
defaultPort: 1e4,
|
|
56
|
+
defaultUser: "",
|
|
57
|
+
fileBased: false
|
|
58
|
+
},
|
|
59
|
+
impala: {
|
|
60
|
+
type: "impala",
|
|
61
|
+
label: "Impala",
|
|
62
|
+
localeKey: "type.impala",
|
|
63
|
+
defaultPort: 21050,
|
|
64
|
+
defaultUser: "",
|
|
65
|
+
fileBased: false
|
|
66
|
+
},
|
|
67
|
+
clickhouse: {
|
|
68
|
+
type: "clickhouse",
|
|
69
|
+
label: "ClickHouse",
|
|
70
|
+
localeKey: "type.clickhouse",
|
|
71
|
+
defaultPort: 8123,
|
|
72
|
+
securePort: 8443,
|
|
73
|
+
defaultUser: "default",
|
|
74
|
+
fileBased: false
|
|
75
|
+
},
|
|
76
|
+
doris: {
|
|
77
|
+
type: "doris",
|
|
78
|
+
label: "Apache Doris",
|
|
79
|
+
localeKey: "type.doris",
|
|
80
|
+
defaultPort: 9030,
|
|
81
|
+
defaultUser: "root",
|
|
82
|
+
fileBased: false
|
|
83
|
+
},
|
|
84
|
+
sqlserver: {
|
|
85
|
+
type: "sqlserver",
|
|
86
|
+
label: "SQL Server",
|
|
87
|
+
localeKey: "type.sqlserver",
|
|
88
|
+
defaultPort: 1433,
|
|
89
|
+
defaultUser: "sa",
|
|
90
|
+
fileBased: false
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
function isDatabaseType(value) {
|
|
94
|
+
return typeof value === "string" && DATABASE_TYPES.includes(value);
|
|
95
|
+
}
|
|
96
|
+
function defaultDatabasePort(type, secure = false) {
|
|
97
|
+
const descriptor = DATABASE_TYPE_DESCRIPTORS[type];
|
|
98
|
+
return secure && descriptor.securePort !== void 0 ? descriptor.securePort : descriptor.defaultPort;
|
|
99
|
+
}
|
|
100
|
+
function defaultDatabaseUser(type) {
|
|
101
|
+
return DATABASE_TYPE_DESCRIPTORS[type].defaultUser;
|
|
102
|
+
}
|
|
103
|
+
function databaseTypeLabel(type) {
|
|
104
|
+
return DATABASE_TYPE_DESCRIPTORS[type].label;
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/defaults.ts
|
|
108
|
+
/**
|
|
109
|
+
* Package-wide defaults shared by the server half (`src/index.ts`) and the
|
|
110
|
+
* database tool half (`src/tool.ts`). Loader schemas carry these as their
|
|
111
|
+
* defaults so a deployment may override every one of them in cordis.yml.
|
|
112
|
+
* @module @yejiming/dsh-data-agent/defaults
|
|
113
|
+
*/
|
|
114
|
+
/** Preset directory name installed into `$DSH_HOME/.agent-presets/`. */
|
|
115
|
+
const DEFAULT_PRESET_ID = "data-agent";
|
|
116
|
+
/** End-to-end deadline for one `/connect` connectivity check, milliseconds. */
|
|
117
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
|
|
118
|
+
/** End-to-end deadline for one database-tool query, milliseconds. */
|
|
119
|
+
const DEFAULT_QUERY_TIMEOUT_MS = 3e4;
|
|
120
|
+
/** In-memory cap on database-tool captured output (stdout and stderr each). */
|
|
121
|
+
const DEFAULT_MAX_RESULT_CHARS = 2e4;
|
|
122
|
+
/** Hard row cap for one structured Web workbench result/export. */
|
|
123
|
+
const WORKBENCH_MAX_EXPORT_ROWS = 5e4;
|
|
124
|
+
/** Bounded capture size for the larger structured Web workbench result. */
|
|
125
|
+
const WORKBENCH_MAX_RESULT_CHARS = 33554432;
|
|
126
|
+
/** Cap on one /query SQL text length (abuse guard; the wire body stays small). */
|
|
127
|
+
const DEFAULT_MAX_QUERY_CHARS = 65536;
|
|
128
|
+
/** Grace period for the subprocess terminate escalation. */
|
|
129
|
+
const DEFAULT_GRACE_MS = 5e3;
|
|
130
|
+
//#endregion
|
|
131
|
+
export { DEFAULT_PRESET_ID as a, WORKBENCH_MAX_RESULT_CHARS as c, defaultDatabasePort as d, defaultDatabaseUser as f, DEFAULT_MAX_RESULT_CHARS as i, DATABASE_TYPES as l, DEFAULT_GRACE_MS as n, DEFAULT_QUERY_TIMEOUT_MS as o, isDatabaseType as p, DEFAULT_MAX_QUERY_CHARS as r, WORKBENCH_MAX_EXPORT_ROWS as s, DEFAULT_CONNECT_TIMEOUT_MS as t, databaseTypeLabel as u };
|
package/lib/ecosystem.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineFacet } from "@dsh-std/sdk";
|
|
2
|
+
//#region src/ecosystem.ts
|
|
3
|
+
/**
|
|
4
|
+
* Community v0.15 host facet.
|
|
5
|
+
*
|
|
6
|
+
* This facet intentionally publishes no commands, tools, UI, routes, storage,
|
|
7
|
+
* credentials, or database effects. The existing Cordis bundle remains the
|
|
8
|
+
* sole functional runtime so hosts may discover the ecosystem declaration
|
|
9
|
+
* without double-registering data-agent behavior.
|
|
10
|
+
*/
|
|
11
|
+
/** Stable degraded snapshot for declaration-only ecosystem discovery. */
|
|
12
|
+
const ECOSYSTEM_SNAPSHOT = Object.freeze({
|
|
13
|
+
state: "degraded",
|
|
14
|
+
message: "Native Cordis runtime owns all data-agent effects; this facet publishes declarations only.",
|
|
15
|
+
extensions: Object.freeze([])
|
|
16
|
+
});
|
|
17
|
+
const ecosystemFacet = defineFacet(() => void 0, () => void 0, () => ECOSYSTEM_SNAPSHOT);
|
|
18
|
+
//#endregion
|
|
19
|
+
export { ECOSYSTEM_SNAPSHOT, ecosystemFacet as default };
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as
|
|
2
|
-
import {
|
|
3
|
-
import { r as apply$1 } from "./command-
|
|
4
|
-
import { n as apply$2 } from "./tool-
|
|
1
|
+
import { a as DEFAULT_PRESET_ID, i as DEFAULT_MAX_RESULT_CHARS, l as DATABASE_TYPES, o as DEFAULT_QUERY_TIMEOUT_MS, r as DEFAULT_MAX_QUERY_CHARS, t as DEFAULT_CONNECT_TIMEOUT_MS } from "./defaults-Cngd8Tf8.js";
|
|
2
|
+
import { c as clientsSchema, t as createConnectionService } from "./connections-CHY4uB6z.js";
|
|
3
|
+
import { r as apply$1 } from "./command-utC5MHd9.js";
|
|
4
|
+
import { n as apply$2 } from "./tool-ZTOS4B33.js";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { access, cp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
7
7
|
import { homedir } from "node:os";
|
|
@@ -29,19 +29,13 @@ const CONNECTION_STORAGE_DOMAIN = "data_agent_connections";
|
|
|
29
29
|
/** Durable profile schema. There is deliberately no `password` field. */
|
|
30
30
|
const persistedConnectionProfileSchema = z$1.object({
|
|
31
31
|
name: z$1.string().min(1).optional(),
|
|
32
|
-
type: z$1.enum(
|
|
33
|
-
"mysql",
|
|
34
|
-
"postgres",
|
|
35
|
-
"sqlite",
|
|
36
|
-
"oracle",
|
|
37
|
-
"hive",
|
|
38
|
-
"impala"
|
|
39
|
-
]),
|
|
32
|
+
type: z$1.enum(DATABASE_TYPES),
|
|
40
33
|
host: z$1.string().optional(),
|
|
41
34
|
port: z$1.number().int().min(1).max(65535).optional(),
|
|
42
35
|
user: z$1.string().optional(),
|
|
43
36
|
database: z$1.string().min(1),
|
|
44
37
|
readonly: z$1.boolean().optional(),
|
|
38
|
+
secure: z$1.boolean().optional(),
|
|
45
39
|
passwordRef: z$1.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).optional(),
|
|
46
40
|
credentialMode: z$1.enum([
|
|
47
41
|
"none",
|
|
@@ -57,19 +51,13 @@ const sessionConnectionBindingSchema = z$1.object({
|
|
|
57
51
|
}).strict();
|
|
58
52
|
/** Session form draft schema. Secret-shaped fields are rejected by strict mode. */
|
|
59
53
|
const persistedConnectionFormDraftSchema = z$1.object({
|
|
60
|
-
type: z$1.enum(
|
|
61
|
-
"mysql",
|
|
62
|
-
"postgres",
|
|
63
|
-
"sqlite",
|
|
64
|
-
"oracle",
|
|
65
|
-
"hive",
|
|
66
|
-
"impala"
|
|
67
|
-
]),
|
|
54
|
+
type: z$1.enum(DATABASE_TYPES),
|
|
68
55
|
host: z$1.string(),
|
|
69
56
|
port: z$1.string(),
|
|
70
57
|
user: z$1.string(),
|
|
71
58
|
database: z$1.string(),
|
|
72
59
|
readonly: z$1.boolean(),
|
|
60
|
+
secure: z$1.boolean().optional(),
|
|
73
61
|
updatedAt: z$1.string().min(1)
|
|
74
62
|
}).strict();
|
|
75
63
|
/** Single source of truth for the storage layout and durable validation. */
|
|
@@ -82,6 +70,15 @@ const connectionStorageSpec = defineDomain({
|
|
|
82
70
|
drafts: domainTable(persistedConnectionFormDraftSchema)
|
|
83
71
|
}
|
|
84
72
|
});
|
|
73
|
+
/** Select the newest successful profile with a deterministic id tie-break. */
|
|
74
|
+
function latestConnectionProfile(entries) {
|
|
75
|
+
let latest;
|
|
76
|
+
for (const [profileId, profile] of entries) if (latest === void 0 || profile.updatedAt > latest.profile.updatedAt || profile.updatedAt === latest.profile.updatedAt && profileId > latest.profileId) latest = {
|
|
77
|
+
profileId,
|
|
78
|
+
profile
|
|
79
|
+
};
|
|
80
|
+
return latest;
|
|
81
|
+
}
|
|
85
82
|
/** Project a typed DSH domain handle onto the service's persistence seam. */
|
|
86
83
|
function createDomainConnectionPersistence(domain) {
|
|
87
84
|
const profiles = domain.table("profiles");
|
|
@@ -91,6 +88,9 @@ function createDomainConnectionPersistence(domain) {
|
|
|
91
88
|
getProfile(profileId) {
|
|
92
89
|
return profiles.get(profileId);
|
|
93
90
|
},
|
|
91
|
+
getLatestProfile() {
|
|
92
|
+
return latestConnectionProfile(profiles.entries());
|
|
93
|
+
},
|
|
94
94
|
putProfile(profileId, profile) {
|
|
95
95
|
return profiles.put(profileId, profile);
|
|
96
96
|
},
|
|
@@ -111,6 +111,9 @@ function createDomainConnectionPersistence(domain) {
|
|
|
111
111
|
},
|
|
112
112
|
putDraft(sessionId, draft) {
|
|
113
113
|
return drafts.put(sessionId, draft);
|
|
114
|
+
},
|
|
115
|
+
deleteDraft(sessionId) {
|
|
116
|
+
return drafts.delete(sessionId);
|
|
114
117
|
}
|
|
115
118
|
};
|
|
116
119
|
}
|
|
@@ -163,13 +166,17 @@ const Config = z.object({
|
|
|
163
166
|
z.const("sqlite"),
|
|
164
167
|
z.const("oracle"),
|
|
165
168
|
z.const("hive"),
|
|
166
|
-
z.const("impala")
|
|
169
|
+
z.const("impala"),
|
|
170
|
+
z.const("clickhouse"),
|
|
171
|
+
z.const("doris"),
|
|
172
|
+
z.const("sqlserver")
|
|
167
173
|
]),
|
|
168
174
|
host: z.string(),
|
|
169
175
|
port: z.natural(),
|
|
170
176
|
user: z.string(),
|
|
171
177
|
database: z.string(),
|
|
172
178
|
readonly: z.boolean(),
|
|
179
|
+
secure: z.boolean(),
|
|
173
180
|
passwordRef: z.string().pattern(/^[A-Za-z_][A-Za-z0-9_]*$/),
|
|
174
181
|
password: z.never().hidden()
|
|
175
182
|
})).default({})
|
|
@@ -186,12 +193,11 @@ function resolveDshHome(env = process.env) {
|
|
|
186
193
|
/**
|
|
187
194
|
* Install the packaged `preset/data-agent/` directory into
|
|
188
195
|
* `$DSH_HOME/.agent-presets/<presetId>/`. Idempotent: an existing target is
|
|
189
|
-
* normally left untouched.
|
|
190
|
-
* migrated once
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* the boot.
|
|
196
|
+
* normally left untouched. Exact package-owned legacy compositions are
|
|
197
|
+
* migrated once when their runtime contract changes; user-edited compositions
|
|
198
|
+
* are never overwritten. `installPreset: false` never calls this. Best-effort
|
|
199
|
+
* — a failure logs a warning with manual install instructions instead of
|
|
200
|
+
* failing the boot.
|
|
195
201
|
*/
|
|
196
202
|
async function installPreset(ctx, presetId) {
|
|
197
203
|
const targetDir = join(resolveDshHome(), ".agent-presets", presetId);
|
|
@@ -210,13 +216,13 @@ async function installPreset(ctx, presetId) {
|
|
|
210
216
|
return false;
|
|
211
217
|
}
|
|
212
218
|
}
|
|
213
|
-
/** SHA-256 of
|
|
214
|
-
const
|
|
219
|
+
/** SHA-256 values of unmodified package-owned compositions safe to migrate. */
|
|
220
|
+
const LEGACY_MANAGED_PRESET_SHA256 = /* @__PURE__ */ new Set(["bae875a90d638ea78715030246b0f8a9f1a2c3359ca61febb6ceb59d0fcd930a", "d3c6f4049580069eec1c6b7de101f12c7fb30482ad317434afb69afb08a91fc6"]);
|
|
215
221
|
/** Public for regression tests of the non-destructive preset migration gate. */
|
|
216
222
|
function isLegacyManagedPreset(source) {
|
|
217
|
-
return createHash("sha256").update(source).digest("hex")
|
|
223
|
+
return LEGACY_MANAGED_PRESET_SHA256.has(createHash("sha256").update(source).digest("hex"));
|
|
218
224
|
}
|
|
219
|
-
/** Upgrade only
|
|
225
|
+
/** Upgrade only exact package-owned legacy compositions; preserve every edited preset. */
|
|
220
226
|
async function synchronizeExistingPreset(ctx, targetDir, sourceDir, presetId) {
|
|
221
227
|
const composition = join(targetDir, "agent.cordis.yml");
|
|
222
228
|
try {
|
|
@@ -224,7 +230,7 @@ async function synchronizeExistingPreset(ctx, targetDir, sourceDir, presetId) {
|
|
|
224
230
|
if (isLegacyManagedPreset(current)) {
|
|
225
231
|
const replacement = await readFile(join(sourceDir, "agent.cordis.yml"), "utf8");
|
|
226
232
|
await writeFile(composition, replacement, "utf8");
|
|
227
|
-
ctx.logger.info("data-agent: migrated preset at %s to
|
|
233
|
+
ctx.logger.info("data-agent: migrated package-owned preset at %s to the current runtime contract", composition);
|
|
228
234
|
return true;
|
|
229
235
|
}
|
|
230
236
|
if (current.includes("@yejiming/dsh-data-agent/tool") || current.includes("@yejiming/dsh-data-agent/command")) {
|
|
@@ -307,7 +313,8 @@ async function apply(ctx, config) {
|
|
|
307
313
|
...spec.port !== void 0 ? { port: spec.port } : {},
|
|
308
314
|
...spec.user !== void 0 ? { user: spec.user } : {},
|
|
309
315
|
...spec.passwordRef !== void 0 ? { passwordRef: spec.passwordRef } : {},
|
|
310
|
-
...spec.readonly !== void 0 ? { readonly: spec.readonly } : {}
|
|
316
|
+
...spec.readonly !== void 0 ? { readonly: spec.readonly } : {},
|
|
317
|
+
...spec.secure !== void 0 ? { secure: spec.secure } : {}
|
|
311
318
|
};
|
|
312
319
|
store.set(sessionId, connection);
|
|
313
320
|
}
|
package/lib/routes.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as DEFAULT_MAX_RESULT_CHARS, o as DEFAULT_QUERY_TIMEOUT_MS, r as DEFAULT_MAX_QUERY_CHARS, t as DEFAULT_CONNECT_TIMEOUT_MS } from "./defaults-
|
|
1
|
+
import { i as DEFAULT_MAX_RESULT_CHARS, l as DATABASE_TYPES, o as DEFAULT_QUERY_TIMEOUT_MS, p as isDatabaseType, r as DEFAULT_MAX_QUERY_CHARS, t as DEFAULT_CONNECT_TIMEOUT_MS } from "./defaults-Cngd8Tf8.js";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import z from "schemastery";
|
|
4
4
|
//#region src/routes.ts
|
|
@@ -20,12 +20,13 @@ function validateConnectBody(value, cwd = process.cwd()) {
|
|
|
20
20
|
const candidate = value;
|
|
21
21
|
const sessionId = requireString(candidate.sessionId, "sessionId");
|
|
22
22
|
const type = candidate.type;
|
|
23
|
-
if (!isDatabaseType(type)) throw new Error(
|
|
23
|
+
if (!isDatabaseType(type)) throw new Error(`type 必须是受支持的数据库类型:${DATABASE_TYPES.join("、")}`);
|
|
24
24
|
const database = requireString(candidate.database, "database");
|
|
25
25
|
const password = optionalString(candidate.password, "password");
|
|
26
26
|
const passwordRef = optionalString(candidate.passwordRef, "passwordRef");
|
|
27
27
|
if (password !== void 0 && passwordRef !== void 0) throw new Error("password 与 passwordRef 不能同时提供");
|
|
28
28
|
const readonly = optionalBoolean(candidate.readonly, "readonly");
|
|
29
|
+
const secure = optionalBoolean(candidate.secure, "secure");
|
|
29
30
|
const profileId = optionalString(candidate.profileId, "profileId");
|
|
30
31
|
const profileName = optionalString(candidate.name, "name");
|
|
31
32
|
const request = {
|
|
@@ -34,6 +35,7 @@ function validateConnectBody(value, cwd = process.cwd()) {
|
|
|
34
35
|
database: type === "sqlite" ? resolve(cwd, database) : database
|
|
35
36
|
};
|
|
36
37
|
if (readonly !== void 0) request.readonly = readonly;
|
|
38
|
+
if (type === "clickhouse" && secure !== void 0) request.secure = secure;
|
|
37
39
|
if (profileId !== void 0) request.profileId = profileId;
|
|
38
40
|
if (profileName !== void 0) request.name = profileName;
|
|
39
41
|
if (type === "sqlite") return request;
|
|
@@ -133,7 +135,7 @@ function apply(ctx, _config) {
|
|
|
133
135
|
const sql = requireString(body.sql, "sql");
|
|
134
136
|
writeJson(200, {
|
|
135
137
|
ok: true,
|
|
136
|
-
result: await scope.dataAgentConnections.
|
|
138
|
+
result: await scope.dataAgentConnections.executeInteractive(sessionId, sql, signal)
|
|
137
139
|
});
|
|
138
140
|
return;
|
|
139
141
|
}
|
|
@@ -177,8 +179,5 @@ function optionalBoolean(value, label) {
|
|
|
177
179
|
if (typeof value !== "boolean") throw new Error(`${label} 必须是布尔值`);
|
|
178
180
|
return value;
|
|
179
181
|
}
|
|
180
|
-
function isDatabaseType(value) {
|
|
181
|
-
return value === "mysql" || value === "postgres" || value === "sqlite" || value === "oracle" || value === "hive" || value === "impala";
|
|
182
|
-
}
|
|
183
182
|
//#endregion
|
|
184
183
|
export { Config, DATA_AGENT_PATH, apply, inject, name, validateConnectBody };
|