@bytebase/dbhub 1.4.0 → 1.5.0
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/dist/{chunk-ABTVMHD6.js → chunk-55X2VY5D.js} +1 -1
- package/dist/chunk-5XSBOK3W.js +63 -0
- package/dist/{chunk-MJVIE3QY.js → chunk-PDKPK25P.js} +286 -81
- package/dist/chunk-SJ5BRPQA.js +500 -0
- package/dist/{chunk-YIGJHEU6.js → chunk-X5OCFRNL.js} +170 -27
- package/dist/index.js +116 -32
- package/dist/mariadb-RWOMZTA6.js +270 -0
- package/dist/mysql-ZXO4TWLG.js +312 -0
- package/dist/{oracle-OUKBU52X.js → oracle-UAVN3F4U.js} +2 -2
- package/dist/{postgres-DC5BDEMU.js → postgres-KCFNDQLG.js} +136 -30
- package/dist/{registry-C7X5G7PA.js → registry-ZIVIYCB2.js} +2 -1
- package/dist/{sqlite-AO2BKIC6.js → sqlite-WKY6543Q.js} +2 -2
- package/dist/{sqlserver-AJUK6L55.js → sqlserver-25MAE77Q.js} +312 -372
- package/package.json +1 -1
- package/dist/chunk-6SZKW6GD.js +0 -179
- package/dist/mariadb-L7Z55ROY.js +0 -551
- package/dist/mysql-XXIHWQGR.js +0 -601
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasMutatingKeyword
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-55X2VY5D.js";
|
|
4
4
|
import {
|
|
5
5
|
blankCommentsAndStrings
|
|
6
6
|
} from "./chunk-IXC4NQGC.js";
|
|
@@ -135,20 +135,124 @@ LIMIT ${maxRows}${semicolon}`;
|
|
|
135
135
|
value: match[1] !== void 0 ? parseInt(match[1], 10) : null
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
|
-
/**
|
|
138
|
+
/**
|
|
139
|
+
* The statement's own TOP clause (SQL Server), located on its own SELECT
|
|
140
|
+
* (after an optional DISTINCT/ALL). `index`/`length` span the `TOP ...`
|
|
141
|
+
* text only, so it can be spliced without disturbing `SELECT DISTINCT`.
|
|
142
|
+
*
|
|
143
|
+
* `value` is the clause's literal row count (`TOP 3`, `TOP (3)`), or null
|
|
144
|
+
* when that number is not an upper bound on the rows returned: a
|
|
145
|
+
* parenthesised expression or parameter (`TOP (@p1)`), `PERCENT`, or
|
|
146
|
+
* `WITH TIES`. Such a TOP cannot simply be tightened; the statement has to
|
|
147
|
+
* be wrapped and capped from the outside.
|
|
148
|
+
*/
|
|
139
149
|
static findTopLevelTop(sql) {
|
|
140
|
-
const match = this.findTopLevelMatch(
|
|
150
|
+
const match = this.findTopLevelMatch(
|
|
151
|
+
sql,
|
|
152
|
+
/\(|\)|\bselect\s+(?:(?:distinct|all)\s+)?(top)\b/gi,
|
|
153
|
+
"first",
|
|
154
|
+
"sqlserver"
|
|
155
|
+
);
|
|
141
156
|
if (match === null) {
|
|
142
157
|
return null;
|
|
143
158
|
}
|
|
144
|
-
|
|
159
|
+
const blanked = blankCommentsAndStrings(sql, "sqlserver");
|
|
160
|
+
const index = match.index + match[0].length - match[1].length;
|
|
161
|
+
let end = match.index + match[0].length;
|
|
162
|
+
let literal;
|
|
163
|
+
const operand = /\s*(?:(\()|(\d+)\b)/y;
|
|
164
|
+
operand.lastIndex = end;
|
|
165
|
+
const operandMatch = operand.exec(blanked);
|
|
166
|
+
if (operandMatch === null) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
end = operand.lastIndex;
|
|
170
|
+
if (operandMatch[1] !== void 0) {
|
|
171
|
+
const close = this.findClosingParen(blanked, end - 1);
|
|
172
|
+
if (close === -1) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const inner = blanked.slice(end, close);
|
|
176
|
+
literal = /^\s*(\d+)\s*$/.exec(inner)?.[1];
|
|
177
|
+
end = close + 1;
|
|
178
|
+
} else {
|
|
179
|
+
literal = operandMatch[2];
|
|
180
|
+
}
|
|
181
|
+
const modifiers = operandMatch[1] !== void 0 ? /(?:\s*percent\b)?(?:\s*with\s+ties\b)?/iy : /(?:\s+percent\b)?(?:\s+with\s+ties\b)?/iy;
|
|
182
|
+
modifiers.lastIndex = end;
|
|
183
|
+
const modifierMatch = modifiers.exec(blanked);
|
|
184
|
+
const unbounded = modifierMatch !== null && modifierMatch[0].length > 0;
|
|
185
|
+
end = modifiers.lastIndex;
|
|
186
|
+
return {
|
|
187
|
+
index,
|
|
188
|
+
length: end - index,
|
|
189
|
+
value: literal !== void 0 && !unbounded ? parseInt(literal, 10) : null
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/** Index of the `)` matching the `(` at `openIndex` in blanked SQL, or -1. */
|
|
193
|
+
static findClosingParen(blankedSQL, openIndex) {
|
|
194
|
+
let depth = 0;
|
|
195
|
+
for (let i = openIndex; i < blankedSQL.length; i++) {
|
|
196
|
+
const ch = blankedSQL[i];
|
|
197
|
+
if (ch === "(") {
|
|
198
|
+
depth++;
|
|
199
|
+
} else if (ch === ")") {
|
|
200
|
+
depth--;
|
|
201
|
+
if (depth === 0) {
|
|
202
|
+
return i;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return -1;
|
|
145
207
|
}
|
|
146
208
|
/**
|
|
147
|
-
* The statement's own SELECT keyword (SQL Server)
|
|
148
|
-
*
|
|
209
|
+
* The statement's own SELECT keyword (SQL Server), together with a
|
|
210
|
+
* DISTINCT/ALL that follows it: T-SQL places TOP after those
|
|
211
|
+
* (`SELECT DISTINCT TOP n`), so that is where a TOP gets inserted. For a
|
|
212
|
+
* CTE this is the final SELECT, not the one inside a CTE body.
|
|
149
213
|
*/
|
|
150
214
|
static findTopLevelSelect(sql) {
|
|
151
|
-
return this.findTopLevelMatch(sql, /\(|\)|\bselect\b
|
|
215
|
+
return this.findTopLevelMatch(sql, /\(|\)|\bselect\b(?:\s+(?:distinct|all)\b)?/gi, "first", "sqlserver");
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* The statement's own `OFFSET ... ROWS [FETCH NEXT n ROWS ONLY]` clause
|
|
219
|
+
* (SQL Server). T-SQL forbids TOP in a query that has OFFSET, so such a
|
|
220
|
+
* statement is capped through its FETCH count instead.
|
|
221
|
+
*
|
|
222
|
+
* `fetch` is the FETCH count (null when the clause has no FETCH);
|
|
223
|
+
* `fetchInsertIndex` is where a FETCH can be appended, or -1 when the
|
|
224
|
+
* OFFSET clause has a shape this scanner does not parse (an arithmetic
|
|
225
|
+
* expression, say), in which case the statement is wrapped.
|
|
226
|
+
*/
|
|
227
|
+
static findTopLevelOffset(sql) {
|
|
228
|
+
const offset = this.findTopLevelMatch(sql, /\(|\)|\boffset\b/gi, "first", "sqlserver");
|
|
229
|
+
if (offset === null) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
const blanked = blankCommentsAndStrings(sql, "sqlserver");
|
|
233
|
+
const clause = /(offset\s+(?:\d+|@\w+|\?)\s+rows?\b)(?:(\s+fetch\s+(?:first|next)\s+)((\d+)|@\w+|\?)\s+rows?\s+only\b)?/iy;
|
|
234
|
+
clause.lastIndex = offset.index;
|
|
235
|
+
const match = clause.exec(blanked);
|
|
236
|
+
if (match === null) {
|
|
237
|
+
return { fetch: null, fetchInsertIndex: -1 };
|
|
238
|
+
}
|
|
239
|
+
if (match[2] === void 0) {
|
|
240
|
+
const end = match.index + match[0].length;
|
|
241
|
+
const unparsedFetch = /\s*fetch\b/iy;
|
|
242
|
+
unparsedFetch.lastIndex = end;
|
|
243
|
+
if (unparsedFetch.test(blanked)) {
|
|
244
|
+
return { fetch: null, fetchInsertIndex: -1 };
|
|
245
|
+
}
|
|
246
|
+
return { fetch: null, fetchInsertIndex: end };
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
fetch: {
|
|
250
|
+
index: match.index + match[1].length + match[2].length,
|
|
251
|
+
length: match[3].length,
|
|
252
|
+
value: match[4] !== void 0 ? parseInt(match[4], 10) : null
|
|
253
|
+
},
|
|
254
|
+
fetchInsertIndex: -1
|
|
255
|
+
};
|
|
152
256
|
}
|
|
153
257
|
/**
|
|
154
258
|
* Check if a SQL statement combines multiple SELECTs with a set operator
|
|
@@ -170,31 +274,72 @@ LIMIT ${maxRows}${semicolon}`;
|
|
|
170
274
|
* Add or modify TOP clause in a SQL statement (SQL Server)
|
|
171
275
|
*/
|
|
172
276
|
static applyTopToQuery(sql, maxRows) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
const orderByClause = body.slice(orderByIndex).trim();
|
|
182
|
-
return `${ctePrefix}SELECT TOP ${maxRows} * FROM (${innerSql}
|
|
183
|
-
) AS subq ${orderByClause}${semicolon}`;
|
|
277
|
+
const offset = this.findTopLevelOffset(sql);
|
|
278
|
+
if (offset !== null) {
|
|
279
|
+
if (offset.fetch !== null && offset.fetch.value !== null) {
|
|
280
|
+
const effectiveFetch = Math.min(offset.fetch.value, maxRows);
|
|
281
|
+
return `${sql.slice(0, offset.fetch.index)}${effectiveFetch}${sql.slice(offset.fetch.index + offset.fetch.length)}`;
|
|
282
|
+
}
|
|
283
|
+
if (offset.fetch === null && offset.fetchInsertIndex !== -1) {
|
|
284
|
+
return `${sql.slice(0, offset.fetchInsertIndex)} FETCH NEXT ${maxRows} ROWS ONLY${sql.slice(offset.fetchInsertIndex)}`;
|
|
184
285
|
}
|
|
185
|
-
return
|
|
186
|
-
|
|
286
|
+
return this.wrapWithTop(sql, maxRows, false);
|
|
287
|
+
}
|
|
288
|
+
if (this.hasSetOperator(sql)) {
|
|
289
|
+
return this.wrapWithTop(sql, maxRows, true);
|
|
187
290
|
}
|
|
188
291
|
const existingTop = this.findTopLevelTop(sql);
|
|
189
292
|
if (existingTop !== null) {
|
|
293
|
+
if (existingTop.value === null) {
|
|
294
|
+
return this.wrapWithTop(sql, maxRows, false);
|
|
295
|
+
}
|
|
190
296
|
const effectiveTop = Math.min(existingTop.value, maxRows);
|
|
191
|
-
return `${sql.slice(0, existingTop.index)}
|
|
297
|
+
return `${sql.slice(0, existingTop.index)}TOP ${effectiveTop}${sql.slice(existingTop.index + existingTop.length)}`;
|
|
192
298
|
}
|
|
193
299
|
const selectMatch = this.findTopLevelSelect(sql);
|
|
194
300
|
if (selectMatch === null) {
|
|
195
301
|
return sql;
|
|
196
302
|
}
|
|
197
|
-
|
|
303
|
+
const insertAt = selectMatch.index + selectMatch[0].length;
|
|
304
|
+
return `${sql.slice(0, insertAt)} TOP ${maxRows}${sql.slice(insertAt)}`;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Cap a statement from the outside: `SELECT TOP n * FROM (<body>) AS subq`.
|
|
308
|
+
*
|
|
309
|
+
* A leading CTE stays outside the derived table: T-SQL has no
|
|
310
|
+
* `SELECT ... FROM (WITH ...) AS subq` form, but a CTE declared before the
|
|
311
|
+
* SELECT is still in scope inside that derived table.
|
|
312
|
+
*
|
|
313
|
+
* T-SQL disallows ORDER BY inside a derived table unless that derived table
|
|
314
|
+
* itself has TOP/OFFSET/FOR XML. With `hoistOrderBy` a top-level trailing
|
|
315
|
+
* ORDER BY moves outside the wrap (the set-operator case, where no TOP
|
|
316
|
+
* belongs to the body as a whole); without it the ORDER BY stays inside,
|
|
317
|
+
* which callers use when the body's own TOP/OFFSET both legalises it and
|
|
318
|
+
* depends on it.
|
|
319
|
+
*/
|
|
320
|
+
static wrapWithTop(sql, maxRows, hoistOrderBy) {
|
|
321
|
+
const { sql: sqlWithoutSemicolon, semicolon } = trimSemicolon(sql);
|
|
322
|
+
const cteIndex = this.findTopLevelSelect(sqlWithoutSemicolon)?.index ?? 0;
|
|
323
|
+
const ctePrefix = sqlWithoutSemicolon.slice(0, cteIndex);
|
|
324
|
+
let body = sqlWithoutSemicolon.slice(cteIndex);
|
|
325
|
+
const optionIndex = this.findTopLevelOptionIndex(body);
|
|
326
|
+
const optionClause = optionIndex === -1 ? "" : ` ${body.slice(optionIndex).trim()}`;
|
|
327
|
+
if (optionIndex !== -1) {
|
|
328
|
+
body = body.slice(0, optionIndex).trimEnd();
|
|
329
|
+
}
|
|
330
|
+
const orderByIndex = hoistOrderBy ? this.findTopLevelOrderByIndex(body) : -1;
|
|
331
|
+
if (orderByIndex !== -1) {
|
|
332
|
+
const innerSql = body.slice(0, orderByIndex).trimEnd();
|
|
333
|
+
const orderByClause = body.slice(orderByIndex).trim();
|
|
334
|
+
return `${ctePrefix}SELECT TOP ${maxRows} * FROM (${innerSql}
|
|
335
|
+
) AS subq ${orderByClause}${optionClause}${semicolon}`;
|
|
336
|
+
}
|
|
337
|
+
return `${ctePrefix}SELECT TOP ${maxRows} * FROM (${body}
|
|
338
|
+
) AS subq${optionClause}${semicolon}`;
|
|
339
|
+
}
|
|
340
|
+
/** Start index of the statement's own trailing `OPTION (...)` query hint, or -1. */
|
|
341
|
+
static findTopLevelOptionIndex(sql) {
|
|
342
|
+
return this.findTopLevelMatch(sql, /\(|\)|\boption\s*(?=\()/gi, "last", "sqlserver")?.index ?? -1;
|
|
198
343
|
}
|
|
199
344
|
/**
|
|
200
345
|
* Apply maxRows limit to a row-returning query only
|
|
@@ -301,11 +446,9 @@ LIMIT ${maxRows}${semicolon}`;
|
|
|
301
446
|
if (!maxRows || !this.isSelectQuery(sql, "sqlserver")) {
|
|
302
447
|
return { sql, probeApplied: false };
|
|
303
448
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return { sql, probeApplied: false };
|
|
308
|
-
}
|
|
449
|
+
const ownCap = this.findTopLevelOffset(sql)?.fetch?.value ?? (this.hasSetOperator(sql) ? null : this.extractTopValue(sql));
|
|
450
|
+
if (ownCap !== null && ownCap <= maxRows) {
|
|
451
|
+
return { sql, probeApplied: false };
|
|
309
452
|
}
|
|
310
453
|
return { sql: this.applyMaxRowsForSQLServer(sql, maxRows + 1), probeApplied: true };
|
|
311
454
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
BUILTIN_TOOL_HEALTH_CHECK,
|
|
6
6
|
BUILTIN_TOOL_SEARCH_OBJECTS,
|
|
7
7
|
ConnectorManager,
|
|
8
|
+
ToolRegistry,
|
|
8
9
|
classifyConnectionError,
|
|
9
10
|
getToolRegistry,
|
|
10
11
|
initializeToolRegistry,
|
|
@@ -18,10 +19,11 @@ import {
|
|
|
18
19
|
resolveSourceConfigs,
|
|
19
20
|
resolveTomlConfigPath,
|
|
20
21
|
resolveTransport
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-PDKPK25P.js";
|
|
22
23
|
import {
|
|
23
24
|
loadConnectors
|
|
24
25
|
} from "./chunk-WVVMH6FJ.js";
|
|
26
|
+
import "./chunk-5XSBOK3W.js";
|
|
25
27
|
import {
|
|
26
28
|
quoteQualifiedIdentifier
|
|
27
29
|
} from "./chunk-X2EC47W4.js";
|
|
@@ -31,7 +33,7 @@ import {
|
|
|
31
33
|
hasEscapeHatchFunction,
|
|
32
34
|
isReadOnlySQL,
|
|
33
35
|
sqlServerDynamicSqlPattern
|
|
34
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-55X2VY5D.js";
|
|
35
37
|
import {
|
|
36
38
|
ConnectorRegistry,
|
|
37
39
|
getDatabaseTypeFromDSN,
|
|
@@ -1633,6 +1635,78 @@ function buildSourceDisplayInfo(sourceConfigs, getToolsForSource2, isDemo) {
|
|
|
1633
1635
|
// src/utils/config-watcher.ts
|
|
1634
1636
|
import fs from "fs";
|
|
1635
1637
|
var DEBOUNCE_MS = 500;
|
|
1638
|
+
function sourceConfigEquals(a, b) {
|
|
1639
|
+
return stableStringify(a) === stableStringify(b);
|
|
1640
|
+
}
|
|
1641
|
+
function stableStringify(value) {
|
|
1642
|
+
if (Array.isArray(value)) {
|
|
1643
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
1644
|
+
}
|
|
1645
|
+
if (value && typeof value === "object") {
|
|
1646
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([x], [y]) => x < y ? -1 : x > y ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`);
|
|
1647
|
+
return `{${entries.join(",")}}`;
|
|
1648
|
+
}
|
|
1649
|
+
return JSON.stringify(value);
|
|
1650
|
+
}
|
|
1651
|
+
function selectTools(applied, rolledBack, newTools, oldTools) {
|
|
1652
|
+
if (newTools === void 0 && oldTools === void 0) {
|
|
1653
|
+
return void 0;
|
|
1654
|
+
}
|
|
1655
|
+
const liveIds = new Set(applied.map((s) => s.id));
|
|
1656
|
+
return [
|
|
1657
|
+
...(newTools ?? []).filter((t) => liveIds.has(t.source) && !rolledBack.has(t.source)),
|
|
1658
|
+
...(oldTools ?? []).filter((t) => rolledBack.has(t.source))
|
|
1659
|
+
];
|
|
1660
|
+
}
|
|
1661
|
+
async function applySourceDiff(connectorManager, oldSources, newSources) {
|
|
1662
|
+
const oldById = new Map(oldSources.map((s) => [s.id, s]));
|
|
1663
|
+
const newById = new Map(newSources.map((s) => [s.id, s]));
|
|
1664
|
+
const applied = /* @__PURE__ */ new Map();
|
|
1665
|
+
const rolledBack = /* @__PURE__ */ new Set();
|
|
1666
|
+
for (const oldSource of oldSources) {
|
|
1667
|
+
const newSource = newById.get(oldSource.id);
|
|
1668
|
+
if (!newSource) {
|
|
1669
|
+
console.error(`Config reload: removing source '${oldSource.id}'`);
|
|
1670
|
+
await connectorManager.removeSource(oldSource.id);
|
|
1671
|
+
} else if (sourceConfigEquals(oldSource, newSource)) {
|
|
1672
|
+
applied.set(oldSource.id, oldSource);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
for (const newSource of newSources) {
|
|
1676
|
+
if (applied.has(newSource.id)) {
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
const oldSource = oldById.get(newSource.id);
|
|
1680
|
+
if (oldSource) {
|
|
1681
|
+
console.error(`Config reload: reconnecting changed source '${newSource.id}'`);
|
|
1682
|
+
await connectorManager.removeSource(newSource.id);
|
|
1683
|
+
} else {
|
|
1684
|
+
console.error(`Config reload: adding source '${newSource.id}'`);
|
|
1685
|
+
}
|
|
1686
|
+
try {
|
|
1687
|
+
await connectorManager.addSource(newSource);
|
|
1688
|
+
applied.set(newSource.id, newSource);
|
|
1689
|
+
} catch (error) {
|
|
1690
|
+
console.error(`Config reload: failed to connect source '${newSource.id}':`, error);
|
|
1691
|
+
if (oldSource) {
|
|
1692
|
+
try {
|
|
1693
|
+
await connectorManager.addSource(oldSource);
|
|
1694
|
+
applied.set(oldSource.id, oldSource);
|
|
1695
|
+
rolledBack.add(oldSource.id);
|
|
1696
|
+
console.error(`Config reload: rolled back source '${oldSource.id}' to its previous config.`);
|
|
1697
|
+
} catch (rollbackError) {
|
|
1698
|
+
console.error(`Config reload: rollback of source '${oldSource.id}' also failed:`, rollbackError);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
const order = newSources.map((s) => s.id);
|
|
1704
|
+
connectorManager.reorderSources(order);
|
|
1705
|
+
return {
|
|
1706
|
+
sources: order.filter((id) => applied.has(id)).map((id) => applied.get(id)),
|
|
1707
|
+
rolledBack
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1636
1710
|
function startConfigWatcher(options) {
|
|
1637
1711
|
const { connectorManager, initialTools } = options;
|
|
1638
1712
|
const configPath = resolveTomlConfigPath();
|
|
@@ -1665,34 +1739,44 @@ Detected change in ${configPath}, reloading configuration...`);
|
|
|
1665
1739
|
console.error("Config reload: failed to load TOML config, keeping existing connections.");
|
|
1666
1740
|
return;
|
|
1667
1741
|
}
|
|
1668
|
-
|
|
1669
|
-
const
|
|
1670
|
-
|
|
1742
|
+
new ToolRegistry({ sources: newConfig.sources, tools: newConfig.tools });
|
|
1743
|
+
const { sources: applied, rolledBack } = await applySourceDiff(
|
|
1744
|
+
connectorManager,
|
|
1745
|
+
lastGoodSources,
|
|
1746
|
+
newConfig.sources
|
|
1747
|
+
);
|
|
1748
|
+
lastGoodSources = applied;
|
|
1749
|
+
let live = applied;
|
|
1750
|
+
let tools = selectTools(applied, rolledBack, newConfig.tools, lastGoodTools);
|
|
1671
1751
|
try {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
});
|
|
1677
|
-
lastGoodSources = newConfig.sources;
|
|
1678
|
-
lastGoodTools = newConfig.tools;
|
|
1679
|
-
console.error("Configuration reloaded successfully.");
|
|
1680
|
-
} catch (connectError) {
|
|
1681
|
-
console.error("Failed to connect with new config, rolling back:", connectError);
|
|
1682
|
-
try {
|
|
1683
|
-
await connectorManager.disconnect();
|
|
1684
|
-
} catch {
|
|
1752
|
+
initializeToolRegistry({ sources: live, tools });
|
|
1753
|
+
} catch (error) {
|
|
1754
|
+
if (rolledBack.size === 0) {
|
|
1755
|
+
throw error;
|
|
1685
1756
|
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1757
|
+
console.error(
|
|
1758
|
+
`Config reload: previous tools of rolled-back source(s) ${[...rolledBack].join(", ")} conflict with the new configuration; taking them offline:`,
|
|
1759
|
+
error
|
|
1760
|
+
);
|
|
1761
|
+
for (const id of rolledBack) {
|
|
1762
|
+
await connectorManager.removeSource(id);
|
|
1692
1763
|
}
|
|
1764
|
+
live = applied.filter((s) => !rolledBack.has(s.id));
|
|
1765
|
+
lastGoodSources = live;
|
|
1766
|
+
tools = selectTools(live, /* @__PURE__ */ new Set(), newConfig.tools, void 0);
|
|
1767
|
+
initializeToolRegistry({ sources: live, tools });
|
|
1768
|
+
}
|
|
1769
|
+
lastGoodTools = tools;
|
|
1770
|
+
const unavailable = newConfig.sources.length - live.length;
|
|
1771
|
+
if (unavailable === 0 && rolledBack.size === 0) {
|
|
1772
|
+
console.error("Configuration reloaded successfully.");
|
|
1773
|
+
} else {
|
|
1774
|
+
console.error(
|
|
1775
|
+
`Configuration reloaded with ${unavailable} source(s) unavailable and ${rolledBack.size} source(s) rolled back to their previous configuration.`
|
|
1776
|
+
);
|
|
1693
1777
|
}
|
|
1694
1778
|
} catch (error) {
|
|
1695
|
-
console.error("Config reload failed
|
|
1779
|
+
console.error("Config reload failed:", error);
|
|
1696
1780
|
} finally {
|
|
1697
1781
|
isReloading = false;
|
|
1698
1782
|
if (reloadPending) {
|
|
@@ -1913,7 +1997,7 @@ See documentation for more details on configuring database connections.
|
|
|
1913
1997
|
const sources = sourceConfigsData.sources;
|
|
1914
1998
|
console.error(`Configuration source: ${sourceConfigsData.source}`);
|
|
1915
1999
|
await connectorManager.connectWithSources(sources);
|
|
1916
|
-
const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-
|
|
2000
|
+
const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-ZIVIYCB2.js");
|
|
1917
2001
|
initializeToolRegistry2({
|
|
1918
2002
|
sources: sourceConfigsData.sources,
|
|
1919
2003
|
tools: sourceConfigsData.tools
|
|
@@ -2068,12 +2152,12 @@ See documentation for more details on configuring database connections.
|
|
|
2068
2152
|
|
|
2069
2153
|
// src/index.ts
|
|
2070
2154
|
var connectorModules = [
|
|
2071
|
-
{ load: () => import("./postgres-
|
|
2072
|
-
{ load: () => import("./sqlserver-
|
|
2073
|
-
{ load: () => import("./sqlite-
|
|
2074
|
-
{ load: () => import("./mysql-
|
|
2075
|
-
{ load: () => import("./mariadb-
|
|
2076
|
-
{ load: () => import("./oracle-
|
|
2155
|
+
{ load: () => import("./postgres-KCFNDQLG.js"), name: "PostgreSQL", driver: "pg" },
|
|
2156
|
+
{ load: () => import("./sqlserver-25MAE77Q.js"), name: "SQL Server", driver: "mssql" },
|
|
2157
|
+
{ load: () => import("./sqlite-WKY6543Q.js"), name: "SQLite", driver: "node:sqlite" },
|
|
2158
|
+
{ load: () => import("./mysql-ZXO4TWLG.js"), name: "MySQL", driver: "mysql2" },
|
|
2159
|
+
{ load: () => import("./mariadb-RWOMZTA6.js"), name: "MariaDB", driver: "mariadb" },
|
|
2160
|
+
{ load: () => import("./oracle-UAVN3F4U.js"), name: "Oracle", driver: "oracledb" }
|
|
2077
2161
|
];
|
|
2078
2162
|
loadConnectors(connectorModules).then(() => main()).catch((error) => {
|
|
2079
2163
|
console.error("Fatal error:", error);
|