@askdb/studio 0.2.0-beta.4 → 0.2.0-beta.40
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 +33 -29
- package/bin/askdb-studio.js +3 -1
- package/dist/bin.d.ts +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +24 -3
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -15
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/index-CgbreUa6.js +100 -0
- package/dist/client/assets/index-DpkWiK_X.css +2 -0
- package/dist/client/index.html +2 -2
- package/dist/execute-registry.d.ts +89 -0
- package/dist/execute-registry.d.ts.map +1 -0
- package/dist/execute-registry.js +445 -0
- package/dist/execute-registry.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection.d.ts +35 -0
- package/dist/introspection.d.ts.map +1 -0
- package/dist/introspection.js +106 -0
- package/dist/introspection.js.map +1 -0
- package/dist/package-manager.d.ts +44 -0
- package/dist/package-manager.d.ts.map +1 -0
- package/dist/package-manager.js +86 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/prisma-install.d.ts +7 -0
- package/dist/prisma-install.d.ts.map +1 -0
- package/dist/prisma-install.js +7 -0
- package/dist/prisma-install.js.map +1 -0
- package/dist/request-guard.d.ts +44 -0
- package/dist/request-guard.d.ts.map +1 -0
- package/dist/request-guard.js +170 -0
- package/dist/request-guard.js.map +1 -0
- package/dist/server.d.ts +22 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1123 -148
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +77 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +511 -0
- package/dist/setup.js.map +1 -0
- package/dist/shared/api.d.ts +176 -3
- package/dist/shared/api.d.ts.map +1 -1
- package/package.json +80 -30
- package/dist/client/assets/index-Bsn2S5X2.css +0 -2
- package/dist/client/assets/index-C_RfRKkd.js +0 -8
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Studio execute-driver registry.
|
|
3
|
+
*
|
|
4
|
+
* Each entry describes a live execute provider — how to dynamically import the
|
|
5
|
+
* driver package, what connection shape it expects, and how to normalize its
|
|
6
|
+
* results into the shared `ExecuteResponse` DTO.
|
|
7
|
+
*
|
|
8
|
+
* Drivers are optional peers. The registry never imports a driver at module
|
|
9
|
+
* load time; every import lives inside an `executeXxx()` function so a missing
|
|
10
|
+
* package only fails when the user actually tries to execute a query.
|
|
11
|
+
*
|
|
12
|
+
* Safety model (every engine):
|
|
13
|
+
*
|
|
14
|
+
* 1. The server validates SQL with `@askdb/core`'s `validateSelectSql` before it
|
|
15
|
+
* reaches a runner ({@link validateExecuteSql}). Runners receive the
|
|
16
|
+
* normalized single statement (no trailing semicolon, no comments).
|
|
17
|
+
* 2. Each runner executes the SQL read-only: inside a read-only transaction
|
|
18
|
+
* (Postgres, MySQL/MariaDB), on a read-only file handle (SQLite), or inside
|
|
19
|
+
* an always-rolled-back transaction (SQL Server). Postgres, MySQL/MariaDB,
|
|
20
|
+
* and SQLite run a single statement; SQL Server runs the SQL as part of a
|
|
21
|
+
* batch. Step 1 rejects a second statement written without `;` there, except
|
|
22
|
+
* one that starts with `FETCH`, or with `END`, `GET` or `MOVE CONVERSATION`.
|
|
23
|
+
* Every engine except SQLite (whose queries can't be interrupted) enforces
|
|
24
|
+
* a statement timeout.
|
|
25
|
+
* 3. Each runner fetches at most `maxRows + 1` rows and reports `truncated`.
|
|
26
|
+
*
|
|
27
|
+
* None of this replaces a read-only database role — point Studio at one.
|
|
28
|
+
*/
|
|
29
|
+
import { getDialectSpec, validateSelectSql, } from "@askdb/core";
|
|
30
|
+
import { loadPgDriver, isPgDriverInstalled } from "@askdb/postgres";
|
|
31
|
+
import { loadMysql2Driver, isMysql2DriverInstalled } from "@askdb/mysql";
|
|
32
|
+
import { loadBetterSqlite3Driver, isBetterSqlite3DriverInstalled } from "@askdb/sqlite";
|
|
33
|
+
import { loadMssqlDriver, isMssqlDriverInstalled, resolveConnectionInput, } from "@askdb/sqlserver";
|
|
34
|
+
export const DEFAULT_EXECUTE_TIMEOUT_MS = 30_000;
|
|
35
|
+
export const DEFAULT_EXECUTE_MAX_ROWS = 500;
|
|
36
|
+
/** Alias for the row-cap subquery wrapper. */
|
|
37
|
+
const ROW_LIMIT_ALIAS = "askdb_q";
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Validation
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
/** Built-in dialects each execute provider can run. The first is the default. */
|
|
42
|
+
const PROVIDER_DIALECTS = {
|
|
43
|
+
postgres: ["postgres", "cockroachdb"],
|
|
44
|
+
mysql: ["mysql", "mariadb"],
|
|
45
|
+
sqlite: ["sqlite"],
|
|
46
|
+
sqlserver: ["sqlserver"],
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* The dialect spec used to validate SQL for `provider`. A configured NL→SQL
|
|
50
|
+
* dialect override (`dialect` in `askdb.config.ts`) is honored when it belongs
|
|
51
|
+
* to the same engine family (e.g. `mariadb` on the `mysql` provider).
|
|
52
|
+
*/
|
|
53
|
+
export function executeDialectFor(provider, dialectOverride) {
|
|
54
|
+
const family = PROVIDER_DIALECTS[provider];
|
|
55
|
+
const id = dialectOverride && family.includes(dialectOverride)
|
|
56
|
+
? dialectOverride
|
|
57
|
+
: family[0];
|
|
58
|
+
return getDialectSpec(id);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Run `@askdb/core`'s read-only SELECT guardrail for the provider's dialect.
|
|
62
|
+
* Returns the single statement without its trailing `;`, so runners can wrap it
|
|
63
|
+
* in a row cap; throws `SqlValidationError`.
|
|
64
|
+
*/
|
|
65
|
+
export function validateExecuteSql(provider, sql, dialectOverride) {
|
|
66
|
+
// `validateSelectSql` keeps a trailing `;`; it is the only `;` left once the
|
|
67
|
+
// statement passes, so dropping it can't touch a string or identifier. Its
|
|
68
|
+
// result is trimmed, so the `;` is the last character. No `\s*;` pattern: it
|
|
69
|
+
// backtracks quadratically on a long whitespace run.
|
|
70
|
+
return validateSelectSql(executeDialectFor(provider, dialectOverride), sql).replace(/;$/, "").trimEnd();
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Normalization helpers
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
function resolveLimits(input) {
|
|
76
|
+
const timeoutMs = positiveInt(input.timeoutMs) ?? DEFAULT_EXECUTE_TIMEOUT_MS;
|
|
77
|
+
const maxRows = positiveInt(input.maxRows) ?? DEFAULT_EXECUTE_MAX_ROWS;
|
|
78
|
+
return { timeoutMs, maxRows, fetchLimit: maxRows + 1 };
|
|
79
|
+
}
|
|
80
|
+
function positiveInt(value) {
|
|
81
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Wrap a validated single SELECT so the database returns at most `fetchLimit`
|
|
85
|
+
* rows. Used for engines with `LIMIT` (Postgres, MySQL). The newlines keep the
|
|
86
|
+
* wrapper intact even if the statement ends in something unexpected.
|
|
87
|
+
*/
|
|
88
|
+
export function wrapWithRowLimit(sql, fetchLimit) {
|
|
89
|
+
return `SELECT * FROM (\n${sql}\n) AS ${ROW_LIMIT_ALIAS} LIMIT ${fetchLimit}`;
|
|
90
|
+
}
|
|
91
|
+
function buildOkResponse(columns, rows, maxRows, durationMs) {
|
|
92
|
+
const truncated = rows.length > maxRows;
|
|
93
|
+
const shown = truncated ? rows.slice(0, maxRows) : rows;
|
|
94
|
+
return {
|
|
95
|
+
ok: true,
|
|
96
|
+
columns,
|
|
97
|
+
rows: shown,
|
|
98
|
+
rowCount: shown.length,
|
|
99
|
+
durationMs,
|
|
100
|
+
truncated,
|
|
101
|
+
rowLimit: maxRows,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function toRowArray(row, columns) {
|
|
105
|
+
if (Array.isArray(row))
|
|
106
|
+
return row;
|
|
107
|
+
const record = (row ?? {});
|
|
108
|
+
return columns.map((c) => record[c]);
|
|
109
|
+
}
|
|
110
|
+
function errorResponse(err) {
|
|
111
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Race `promise` against a timer. On timeout, run `onTimeout` (cancel/destroy
|
|
115
|
+
* the connection) and reject. A client-side backstop for server-side timeouts.
|
|
116
|
+
*/
|
|
117
|
+
async function withTimeout(promise, ms, onTimeout) {
|
|
118
|
+
let timer;
|
|
119
|
+
const timeout = new Promise((_, reject) => {
|
|
120
|
+
timer = setTimeout(() => {
|
|
121
|
+
try {
|
|
122
|
+
onTimeout();
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// best effort
|
|
126
|
+
}
|
|
127
|
+
reject(new Error(`Query timed out after ${ms} ms.`));
|
|
128
|
+
}, ms);
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
return await Promise.race([promise, timeout]);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Grace period before the client-side backstop fires after the server-side timeout. */
|
|
138
|
+
const CLIENT_TIMEOUT_GRACE_MS = 2_000;
|
|
139
|
+
async function executePostgres(input) {
|
|
140
|
+
const { connectionString, sql, params, projectRoot } = input;
|
|
141
|
+
const { timeoutMs, maxRows, fetchLimit } = resolveLimits(input);
|
|
142
|
+
if (!connectionString) {
|
|
143
|
+
return { ok: false, error: "No connection URL configured for Postgres execute. Set studio.execute.databaseUrl in askdb.config.ts." };
|
|
144
|
+
}
|
|
145
|
+
let pgMod;
|
|
146
|
+
try {
|
|
147
|
+
pgMod = await loadPgDriver({ resolveFrom: projectRoot });
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
return errorResponse(err);
|
|
151
|
+
}
|
|
152
|
+
const client = new pgMod.Client({
|
|
153
|
+
connectionString,
|
|
154
|
+
connectionTimeoutMillis: timeoutMs,
|
|
155
|
+
// Client-side backstop; the server-side statement_timeout below fires first.
|
|
156
|
+
query_timeout: timeoutMs + CLIENT_TIMEOUT_GRACE_MS,
|
|
157
|
+
});
|
|
158
|
+
try {
|
|
159
|
+
await client.connect();
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
return errorResponse(err);
|
|
163
|
+
}
|
|
164
|
+
const startMs = Date.now();
|
|
165
|
+
try {
|
|
166
|
+
// Session default + explicit read-only transaction: even a statement that
|
|
167
|
+
// slipped past validation cannot write, and cannot COMMIT its way out
|
|
168
|
+
// (the extended protocol below runs exactly one statement).
|
|
169
|
+
await client.query("SET default_transaction_read_only = on");
|
|
170
|
+
await client.query("BEGIN READ ONLY");
|
|
171
|
+
await client.query(`SET LOCAL statement_timeout = ${timeoutMs}`);
|
|
172
|
+
const result = await client.query({
|
|
173
|
+
text: wrapWithRowLimit(sql, fetchLimit),
|
|
174
|
+
values: params,
|
|
175
|
+
queryMode: "extended",
|
|
176
|
+
name: "askdb_studio_execute",
|
|
177
|
+
rowMode: "array",
|
|
178
|
+
});
|
|
179
|
+
await client.query("ROLLBACK");
|
|
180
|
+
const durationMs = Date.now() - startMs;
|
|
181
|
+
const columns = result.fields.map((f) => f.name);
|
|
182
|
+
const rows = result.rows.map((r) => toRowArray(r, columns));
|
|
183
|
+
return buildOkResponse(columns, rows, maxRows, durationMs);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
await client.query("ROLLBACK").catch(() => { });
|
|
187
|
+
return errorResponse(err);
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
await client.end().catch(() => { });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** MySQL uses `max_execution_time` (ms); MariaDB uses `max_statement_time` (seconds). */
|
|
194
|
+
async function applyMysqlTimeout(conn, timeoutMs) {
|
|
195
|
+
try {
|
|
196
|
+
await conn.query(`SET SESSION MAX_EXECUTION_TIME = ${timeoutMs}`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Not MySQL 5.7.8+ — try MariaDB.
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
await conn.query(`SET SESSION max_statement_time = ${Math.max(timeoutMs / 1000, 0.001)}`);
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Neither variable exists; the client-side backstop still applies.
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function executeMySQL(input) {
|
|
210
|
+
const { connectionString, sql, params, projectRoot } = input;
|
|
211
|
+
const { timeoutMs, maxRows, fetchLimit } = resolveLimits(input);
|
|
212
|
+
if (!connectionString) {
|
|
213
|
+
return { ok: false, error: "No connection URL configured for MySQL execute. Set studio.execute.databaseUrl in askdb.config.ts." };
|
|
214
|
+
}
|
|
215
|
+
let mysql2Mod;
|
|
216
|
+
try {
|
|
217
|
+
mysql2Mod = await loadMysql2Driver({ resolveFrom: projectRoot });
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
return errorResponse(err);
|
|
221
|
+
}
|
|
222
|
+
let conn;
|
|
223
|
+
try {
|
|
224
|
+
conn = await mysql2Mod.createConnection({
|
|
225
|
+
uri: connectionString,
|
|
226
|
+
multipleStatements: false,
|
|
227
|
+
connectTimeout: timeoutMs,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
return errorResponse(err);
|
|
232
|
+
}
|
|
233
|
+
const startMs = Date.now();
|
|
234
|
+
try {
|
|
235
|
+
await applyMysqlTimeout(conn, timeoutMs);
|
|
236
|
+
await conn.query("SET SESSION TRANSACTION READ ONLY");
|
|
237
|
+
await conn.query("START TRANSACTION READ ONLY");
|
|
238
|
+
// `execute` uses the binary prepared-statement protocol: one statement only.
|
|
239
|
+
const [rowsRaw, fields] = await withTimeout(conn.execute({ sql: wrapWithRowLimit(sql, fetchLimit), values: params, rowsAsArray: true }), timeoutMs + CLIENT_TIMEOUT_GRACE_MS, () => conn.destroy?.());
|
|
240
|
+
await conn.query("ROLLBACK");
|
|
241
|
+
const durationMs = Date.now() - startMs;
|
|
242
|
+
const columns = (fields ?? []).map((f) => f.name);
|
|
243
|
+
const rows = (rowsRaw ?? []).map((r) => toRowArray(r, columns));
|
|
244
|
+
return buildOkResponse(columns, rows, maxRows, durationMs);
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
await conn.query("ROLLBACK").catch(() => { });
|
|
248
|
+
return errorResponse(err);
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
await conn.end().catch(() => { });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function executeSQLite(input) {
|
|
255
|
+
const { file, sql, params, projectRoot } = input;
|
|
256
|
+
const { timeoutMs, maxRows, fetchLimit } = resolveLimits(input);
|
|
257
|
+
if (!file) {
|
|
258
|
+
return { ok: false, error: "No SQLite file path configured for execute. Set studio.execute.file in askdb.config.ts." };
|
|
259
|
+
}
|
|
260
|
+
let Sqlite3;
|
|
261
|
+
try {
|
|
262
|
+
const mod = await loadBetterSqlite3Driver({ resolveFrom: projectRoot });
|
|
263
|
+
Sqlite3 = mod.default;
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
return errorResponse(err);
|
|
267
|
+
}
|
|
268
|
+
const startMs = Date.now();
|
|
269
|
+
let db;
|
|
270
|
+
try {
|
|
271
|
+
// Read-only handle. `timeout` is only the busy (lock-wait) timeout —
|
|
272
|
+
// better-sqlite3 runs queries synchronously and cannot interrupt them.
|
|
273
|
+
db = new Sqlite3(file, { readonly: true, fileMustExist: true, timeout: timeoutMs });
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
return errorResponse(err);
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
// `prepare` rejects strings containing more than one statement.
|
|
280
|
+
const stmt = db.prepare(sql);
|
|
281
|
+
if (!stmt.reader) {
|
|
282
|
+
return { ok: false, error: "Only statements that return rows can be executed." };
|
|
283
|
+
}
|
|
284
|
+
stmt.raw(true);
|
|
285
|
+
const columns = stmt.columns().map((c) => c.name);
|
|
286
|
+
const rows = [];
|
|
287
|
+
// Stream rows and stop at the cap — never materialize the full result.
|
|
288
|
+
for (const row of stmt.iterate(...params)) {
|
|
289
|
+
rows.push(toRowArray(row, columns));
|
|
290
|
+
if (rows.length >= fetchLimit)
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
const durationMs = Date.now() - startMs;
|
|
294
|
+
return buildOkResponse(columns, rows, maxRows, durationMs);
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
return errorResponse(err);
|
|
298
|
+
}
|
|
299
|
+
finally {
|
|
300
|
+
db.close();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Rewrite `$1`, `$2`, ... or bare `?` positional params to MSSQL `@p0`, `@p1`, ...
|
|
305
|
+
* and return an object of named bindings. SQL that already uses `@pN` markers (from
|
|
306
|
+
* `ask()` with the sqlserver dialect) is bound as written: rewriting it would turn a `?`
|
|
307
|
+
* or `$…` inside a string literal, or a money literal, into a marker.
|
|
308
|
+
*/
|
|
309
|
+
function rewriteSqlServerParams(sql, params) {
|
|
310
|
+
if (params.length === 0)
|
|
311
|
+
return { sql, bindings: {} };
|
|
312
|
+
const bindings = {};
|
|
313
|
+
params.forEach((value, idx) => {
|
|
314
|
+
bindings[`p${idx}`] = value;
|
|
315
|
+
});
|
|
316
|
+
if (/@p\d/.test(sql))
|
|
317
|
+
return { sql, bindings };
|
|
318
|
+
// Replace $N placeholders (1-indexed) first, then bare ? placeholders.
|
|
319
|
+
let idx = 0;
|
|
320
|
+
const rewritten = sql
|
|
321
|
+
.replace(/\$\d+/g, () => `@p${idx++}`)
|
|
322
|
+
.replace(/\?/g, () => `@p${idx++}`);
|
|
323
|
+
return { sql: rewritten, bindings };
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* SQL Server has no read-only transaction mode, so the statement runs inside a
|
|
327
|
+
* transaction that is always rolled back. `XACT_ABORT` rolls back on any error;
|
|
328
|
+
* `ROWCOUNT` caps the rows returned (SQL Server has no `LIMIT`, and wrapping in
|
|
329
|
+
* a derived table would reject unnamed columns such as `COUNT(*)`).
|
|
330
|
+
*/
|
|
331
|
+
export function buildSqlServerBatch(sql, fetchLimit) {
|
|
332
|
+
return [
|
|
333
|
+
"SET XACT_ABORT ON;",
|
|
334
|
+
`SET ROWCOUNT ${fetchLimit};`,
|
|
335
|
+
"BEGIN TRANSACTION;",
|
|
336
|
+
sql,
|
|
337
|
+
";",
|
|
338
|
+
"IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;",
|
|
339
|
+
"SET ROWCOUNT 0;",
|
|
340
|
+
].join("\n");
|
|
341
|
+
}
|
|
342
|
+
function recordsetColumns(recordset) {
|
|
343
|
+
if (recordset.columns) {
|
|
344
|
+
return Object.values(recordset.columns)
|
|
345
|
+
.sort((a, b) => a.index - b.index)
|
|
346
|
+
.map((c) => c.name);
|
|
347
|
+
}
|
|
348
|
+
return recordset.length > 0 ? Object.keys(recordset[0]) : [];
|
|
349
|
+
}
|
|
350
|
+
async function executeSQLServer(input) {
|
|
351
|
+
const { connectionString, sql, params, projectRoot } = input;
|
|
352
|
+
const { timeoutMs, maxRows, fetchLimit } = resolveLimits(input);
|
|
353
|
+
if (!connectionString) {
|
|
354
|
+
return { ok: false, error: "No connection URL configured for SQL Server execute. Set studio.execute.databaseUrl in askdb.config.ts." };
|
|
355
|
+
}
|
|
356
|
+
let mssqlMod;
|
|
357
|
+
try {
|
|
358
|
+
mssqlMod = await loadMssqlDriver({ resolveFrom: projectRoot });
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
return errorResponse(err);
|
|
362
|
+
}
|
|
363
|
+
let pool;
|
|
364
|
+
try {
|
|
365
|
+
pool = await new mssqlMod.ConnectionPool(resolveConnectionInput(connectionString)).connect();
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
return errorResponse(err);
|
|
369
|
+
}
|
|
370
|
+
const startMs = Date.now();
|
|
371
|
+
try {
|
|
372
|
+
const { sql: rewrittenSql, bindings } = rewriteSqlServerParams(sql, params);
|
|
373
|
+
const req = pool.request();
|
|
374
|
+
for (const [name, value] of Object.entries(bindings)) {
|
|
375
|
+
req.input(name, value);
|
|
376
|
+
}
|
|
377
|
+
const result = await withTimeout(req.query(buildSqlServerBatch(rewrittenSql, fetchLimit)), timeoutMs, () => req.cancel?.());
|
|
378
|
+
const durationMs = Date.now() - startMs;
|
|
379
|
+
const recordset = result.recordset ?? result.recordsets?.[0] ?? [];
|
|
380
|
+
const columns = recordsetColumns(recordset);
|
|
381
|
+
const rows = recordset.map((r) => toRowArray(r, columns));
|
|
382
|
+
return buildOkResponse(columns, rows, maxRows, durationMs);
|
|
383
|
+
}
|
|
384
|
+
catch (err) {
|
|
385
|
+
return errorResponse(err);
|
|
386
|
+
}
|
|
387
|
+
finally {
|
|
388
|
+
await pool.close().catch(() => { });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// ---------------------------------------------------------------------------
|
|
392
|
+
// Registry
|
|
393
|
+
// ---------------------------------------------------------------------------
|
|
394
|
+
export const EXECUTE_DRIVER_REGISTRY = {
|
|
395
|
+
postgres: {
|
|
396
|
+
provider: "postgres",
|
|
397
|
+
label: "Postgres",
|
|
398
|
+
packageName: "pg",
|
|
399
|
+
installCommand: "pnpm add pg",
|
|
400
|
+
execute: executePostgres,
|
|
401
|
+
},
|
|
402
|
+
mysql: {
|
|
403
|
+
provider: "mysql",
|
|
404
|
+
label: "MySQL",
|
|
405
|
+
packageName: "mysql2",
|
|
406
|
+
installCommand: "pnpm add mysql2",
|
|
407
|
+
execute: executeMySQL,
|
|
408
|
+
},
|
|
409
|
+
sqlite: {
|
|
410
|
+
provider: "sqlite",
|
|
411
|
+
label: "SQLite",
|
|
412
|
+
packageName: "better-sqlite3",
|
|
413
|
+
installCommand: "pnpm add better-sqlite3",
|
|
414
|
+
execute: executeSQLite,
|
|
415
|
+
},
|
|
416
|
+
sqlserver: {
|
|
417
|
+
provider: "sqlserver",
|
|
418
|
+
label: "SQL Server",
|
|
419
|
+
packageName: "mssql",
|
|
420
|
+
installCommand: "pnpm add mssql",
|
|
421
|
+
execute: executeSQLServer,
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
/** True when `value` is a registry key (own property — rejects `constructor`, `__proto__`, …). */
|
|
425
|
+
export function isStudioExecuteProvider(value) {
|
|
426
|
+
return typeof value === "string" && Object.hasOwn(EXECUTE_DRIVER_REGISTRY, value);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Check whether a driver package is resolvable from the user's project root.
|
|
430
|
+
*/
|
|
431
|
+
export function isDriverInstalled(packageName, projectRoot) {
|
|
432
|
+
switch (packageName) {
|
|
433
|
+
case "pg":
|
|
434
|
+
return isPgDriverInstalled({ resolveFrom: projectRoot });
|
|
435
|
+
case "mysql2":
|
|
436
|
+
return isMysql2DriverInstalled({ resolveFrom: projectRoot });
|
|
437
|
+
case "better-sqlite3":
|
|
438
|
+
return isBetterSqlite3DriverInstalled({ resolveFrom: projectRoot });
|
|
439
|
+
case "mssql":
|
|
440
|
+
return isMssqlDriverInstalled({ resolveFrom: projectRoot });
|
|
441
|
+
default:
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
//# sourceMappingURL=execute-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-registry.js","sourceRoot":"","sources":["../src/execute-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ConnectorProviderId } from "@askdb/introspect";
|
|
2
|
+
export type StudioIntrospectionPlan = {
|
|
3
|
+
ok: true;
|
|
4
|
+
engine: ConnectorProviderId;
|
|
5
|
+
sourceLabel: string;
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
engine: ConnectorProviderId | null;
|
|
9
|
+
error: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolve what a server-side introspection run would do, from the runtime
|
|
13
|
+
* config alone: the config's provider (its adapter loaded), and the connection its adapter's
|
|
14
|
+
* `resolveConnection` hook resolves (the same registry call the CLI makes).
|
|
15
|
+
* Never includes credentials in `sourceLabel` — it is shown in the UI.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveStudioIntrospectionPlan(): Promise<StudioIntrospectionPlan>;
|
|
18
|
+
export type StudioIntrospectionRun = {
|
|
19
|
+
engine: ConnectorProviderId;
|
|
20
|
+
schemaId: string;
|
|
21
|
+
tables: number;
|
|
22
|
+
warnings: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Run introspection server-side into `outDir`, preserving any existing
|
|
26
|
+
* enrichment markdown (the writer keeps `tables/*.md`, `concepts.md`, and
|
|
27
|
+
* `tenant-policy.md` when `existingArtifactDir` is supplied — the same
|
|
28
|
+
* guarantee `askdb introspect` gives).
|
|
29
|
+
*/
|
|
30
|
+
export declare function runStudioIntrospection(options: {
|
|
31
|
+
outDir: string;
|
|
32
|
+
schemaId?: string;
|
|
33
|
+
hasExistingArtifact: boolean;
|
|
34
|
+
}): Promise<StudioIntrospectionRun>;
|
|
35
|
+
//# sourceMappingURL=introspection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AA+B3B,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAevF;AAaD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAoClC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { getAskDbRuntimeConfig } from "@askdb/config";
|
|
3
|
+
import { connectorPackageMissingMessage, createConnectorRegistry, introspect, } from "@askdb/introspect";
|
|
4
|
+
import { createOptionalDriverLoader, rethrowDriverImportError } from "@askdb/introspect/kit";
|
|
5
|
+
import { postgresConnectorProvider } from "@askdb/postgres";
|
|
6
|
+
import { mysqlConnectorProvider } from "@askdb/mysql";
|
|
7
|
+
import { sqliteConnectorProvider } from "@askdb/sqlite";
|
|
8
|
+
import { sqlServerConnectorProvider } from "@askdb/sqlserver";
|
|
9
|
+
import { PRISMA_BUILD_APPROVALS } from "./prisma-install.js";
|
|
10
|
+
/**
|
|
11
|
+
* `@askdb/prisma` is an optional peer of Studio, as of `askdb` (#259). It is imported
|
|
12
|
+
* only when the config selects the prisma engine, from Studio's install first, then
|
|
13
|
+
* from the project in the working directory. The CLI registers it the same way.
|
|
14
|
+
*/
|
|
15
|
+
const prismaPackage = createOptionalDriverLoader({
|
|
16
|
+
packageName: "@askdb/prisma",
|
|
17
|
+
importDriver: () => import("@askdb/prisma").catch(rethrowDriverImportError),
|
|
18
|
+
missingMessage: connectorPackageMissingMessage({
|
|
19
|
+
provider: "prisma",
|
|
20
|
+
packageName: "@askdb/prisma",
|
|
21
|
+
allowBuilds: PRISMA_BUILD_APPROVALS,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
const connectorRegistry = createConnectorRegistry([
|
|
25
|
+
postgresConnectorProvider,
|
|
26
|
+
mysqlConnectorProvider,
|
|
27
|
+
sqliteConnectorProvider,
|
|
28
|
+
sqlServerConnectorProvider,
|
|
29
|
+
{ provider: "prisma", load: async () => (await prismaPackage.load()).prismaConnectorProvider },
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* Resolve what a server-side introspection run would do, from the runtime
|
|
33
|
+
* config alone: the config's provider (its adapter loaded), and the connection its adapter's
|
|
34
|
+
* `resolveConnection` hook resolves (the same registry call the CLI makes).
|
|
35
|
+
* Never includes credentials in `sourceLabel` — it is shown in the UI.
|
|
36
|
+
*/
|
|
37
|
+
export async function resolveStudioIntrospectionPlan() {
|
|
38
|
+
const rt = getAskDbRuntimeConfig();
|
|
39
|
+
const engine = rt.introspection.provider;
|
|
40
|
+
if (!connectorRegistry.hasProvider(engine)) {
|
|
41
|
+
return { ok: false, engine: null, error: `Unsupported introspection provider: ${engine}` };
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
// Imports an optional engine package (`@askdb/prisma`); a missing one is the plan's error.
|
|
45
|
+
await connectorRegistry.load(engine);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return { ok: false, engine, error: error instanceof Error ? error.message : String(error) };
|
|
49
|
+
}
|
|
50
|
+
const connection = resolveConnection(engine);
|
|
51
|
+
if (!connection.ok)
|
|
52
|
+
return { ok: false, engine, error: connection.error };
|
|
53
|
+
return { ok: true, engine, sourceLabel: connection.sourceLabel };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The engine's adapter resolves its connection from askdb.config/env (the same
|
|
57
|
+
* hook the CLI uses) and phrases missing-config errors in terms of config keys.
|
|
58
|
+
*/
|
|
59
|
+
function resolveConnection(engine) {
|
|
60
|
+
return connectorRegistry.resolveConnection(engine, {
|
|
61
|
+
runtime: getAskDbRuntimeConfig(),
|
|
62
|
+
surface: "studio",
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Run introspection server-side into `outDir`, preserving any existing
|
|
67
|
+
* enrichment markdown (the writer keeps `tables/*.md`, `concepts.md`, and
|
|
68
|
+
* `tenant-policy.md` when `existingArtifactDir` is supplied — the same
|
|
69
|
+
* guarantee `askdb introspect` gives).
|
|
70
|
+
*/
|
|
71
|
+
export async function runStudioIntrospection(options) {
|
|
72
|
+
const plan = await resolveStudioIntrospectionPlan();
|
|
73
|
+
if (!plan.ok)
|
|
74
|
+
throw new Error(plan.error);
|
|
75
|
+
const connection = resolveConnection(plan.engine);
|
|
76
|
+
if (!connection.ok)
|
|
77
|
+
throw new Error(connection.error);
|
|
78
|
+
const schemaId = options.schemaId ?? inferSchemaId(options.outDir);
|
|
79
|
+
// Resync reads the same schema list `askdb introspect` does (introspection.schemas).
|
|
80
|
+
const schemas = getAskDbRuntimeConfig().introspection.schemas;
|
|
81
|
+
const connectorConfig = {
|
|
82
|
+
provider: plan.engine,
|
|
83
|
+
...connection.connection,
|
|
84
|
+
schemaId,
|
|
85
|
+
...(schemas ? { filters: { schemas } } : {}),
|
|
86
|
+
};
|
|
87
|
+
const runConfig = connectorRegistry.createConnector(connectorConfig);
|
|
88
|
+
const connector = runConfig.connector;
|
|
89
|
+
const result = await introspect(runConfig.input, {
|
|
90
|
+
outDir: options.outDir,
|
|
91
|
+
schemaId,
|
|
92
|
+
existingArtifactDir: options.hasExistingArtifact ? options.outDir : undefined,
|
|
93
|
+
}, { connector });
|
|
94
|
+
return {
|
|
95
|
+
engine: plan.engine,
|
|
96
|
+
schemaId,
|
|
97
|
+
tables: result.schema.schemas.reduce((sum, namespace) => sum + namespace.tables.length, 0),
|
|
98
|
+
warnings: result.warnings.map((warning) => typeof warning === "string" ? warning : JSON.stringify(warning)),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function inferSchemaId(path) {
|
|
102
|
+
const name = basename(path);
|
|
103
|
+
const inferred = name.endsWith(".schema") ? name.slice(0, -".schema".length) : name;
|
|
104
|
+
return inferred || "introspected";
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=introspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspection.js","sourceRoot":"","sources":["../src/introspection.ts"],"names":[],"mappings":"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"}
|