grain-tools 0.10.15 → 0.10.16
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/connection-setup.html +17921 -0
- package/dist/credential-page.html +4965 -0
- package/dist/mcp-app.html +67 -13
- package/dist/web-app.html +356 -117
- package/out/server/standalone.js +164375 -162709
- package/package.json +4 -2
- package/server.json +2 -2
package/dist/web-app.html
CHANGED
|
@@ -12820,7 +12820,7 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12820
12820
|
chartsEnabled: false,
|
|
12821
12821
|
mcpEnabled: false,
|
|
12822
12822
|
mcpEntitled: false,
|
|
12823
|
-
|
|
12823
|
+
grainServiceSetup: "registered",
|
|
12824
12824
|
mcpSafeMode: true,
|
|
12825
12825
|
activeConnectorType: null,
|
|
12826
12826
|
activeConnectionId: null,
|
|
@@ -12910,7 +12910,7 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12910
12910
|
"filterResultsByActiveFile",
|
|
12911
12911
|
"mcpEnabled",
|
|
12912
12912
|
"mcpEntitled",
|
|
12913
|
-
"
|
|
12913
|
+
"grainServiceSetup",
|
|
12914
12914
|
"mcpSafeMode",
|
|
12915
12915
|
"activeConnectorType",
|
|
12916
12916
|
"activeConnectionId",
|
|
@@ -13073,6 +13073,7 @@ const ALL_TOOLS = [
|
|
|
13073
13073
|
"list_connections",
|
|
13074
13074
|
"get_demo_dataset",
|
|
13075
13075
|
"save_connection",
|
|
13076
|
+
"create_connection_draft",
|
|
13076
13077
|
"request_connection_credentials",
|
|
13077
13078
|
"test_connection",
|
|
13078
13079
|
"delete_connection",
|
|
@@ -13170,6 +13171,7 @@ const TELEMETRY_CONNECTORS = [
|
|
|
13170
13171
|
];
|
|
13171
13172
|
const TELEMETRY_TOOL_NAMES = [...ALL_TOOLS, "unknown"];
|
|
13172
13173
|
const TELEMETRY_COMMAND_IDS = [
|
|
13174
|
+
"grain.setUpService",
|
|
13173
13175
|
"grain.showDaemonInfo",
|
|
13174
13176
|
"grain.mcp.restart",
|
|
13175
13177
|
"grain.mcp.testConnection",
|
|
@@ -13510,6 +13512,8 @@ const TELEMETRY_ERROR_IDS = [
|
|
|
13510
13512
|
* Not a database error: nothing was ever sent to a connector.
|
|
13511
13513
|
*/
|
|
13512
13514
|
"credential_required",
|
|
13515
|
+
"setup_required",
|
|
13516
|
+
"connection_draft_rejected",
|
|
13513
13517
|
/**
|
|
13514
13518
|
* The session holding this query's tab was evicted (SessionManager's maxSessions
|
|
13515
13519
|
* cap) while the query was still running, so the result had nowhere to land.
|
|
@@ -13774,7 +13778,24 @@ async function buildGuideHubState() {
|
|
|
13774
13778
|
return { ...DEFAULT_GUIDE_HUB_STATE, telemetryEnabled };
|
|
13775
13779
|
}
|
|
13776
13780
|
}
|
|
13777
|
-
const
|
|
13781
|
+
const WEB_SESSION_KEY = "grain:web-session-id";
|
|
13782
|
+
function resolveWebSessionId() {
|
|
13783
|
+
try {
|
|
13784
|
+
const stored = window.sessionStorage.getItem(WEB_SESSION_KEY);
|
|
13785
|
+
if (stored && /^web-[0-9a-f-]{36}$/.test(stored)) return stored;
|
|
13786
|
+
} catch {
|
|
13787
|
+
return `web-${crypto.randomUUID()}`;
|
|
13788
|
+
}
|
|
13789
|
+
return `web-${crypto.randomUUID()}`;
|
|
13790
|
+
}
|
|
13791
|
+
const WEB_SESSION_ID = resolveWebSessionId();
|
|
13792
|
+
function rememberWebSessionId() {
|
|
13793
|
+
try {
|
|
13794
|
+
window.sessionStorage.setItem(WEB_SESSION_KEY, WEB_SESSION_ID);
|
|
13795
|
+
} catch {
|
|
13796
|
+
return;
|
|
13797
|
+
}
|
|
13798
|
+
}
|
|
13778
13799
|
function resolveProjectedTarget(tabId, payload) {
|
|
13779
13800
|
const parsed = tabId ? parseProjectedTabId(tabId) : void 0;
|
|
13780
13801
|
const tab = tabId ? useAppStore.getState().tabs.find((t) => t.id === tabId) : void 0;
|
|
@@ -14166,6 +14187,7 @@ function useWebTabSync(options) {
|
|
|
14166
14187
|
}
|
|
14167
14188
|
}
|
|
14168
14189
|
unreachableStreakRef.current = 0;
|
|
14190
|
+
rememberWebSessionId();
|
|
14169
14191
|
setDaemonStatus("connected");
|
|
14170
14192
|
setIsReady(true);
|
|
14171
14193
|
} catch (err) {
|
|
@@ -14214,7 +14236,8 @@ function useWebToolProxy() {
|
|
|
14214
14236
|
query: args.sql,
|
|
14215
14237
|
sessionId,
|
|
14216
14238
|
connectionId: args.connectionId,
|
|
14217
|
-
tabId: args.tabId
|
|
14239
|
+
tabId: args.tabId,
|
|
14240
|
+
title: args.title
|
|
14218
14241
|
});
|
|
14219
14242
|
if (!ok) {
|
|
14220
14243
|
throw new Error(data.error || "Query failed");
|
|
@@ -14330,29 +14353,29 @@ function ReauthorizeNotice({
|
|
|
14330
14353
|
const [copied, setCopied] = reactExports.useState(false);
|
|
14331
14354
|
const copyCommand = async () => {
|
|
14332
14355
|
try {
|
|
14333
|
-
await navigator.clipboard.writeText("grain
|
|
14356
|
+
await navigator.clipboard.writeText("grain ui");
|
|
14334
14357
|
setCopied(true);
|
|
14335
14358
|
} catch {
|
|
14336
14359
|
setCopied(false);
|
|
14337
14360
|
}
|
|
14338
14361
|
};
|
|
14339
14362
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth", role: "alert", children: [
|
|
14340
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: "Grain is running. Reconnect this browser tab." }),
|
|
14363
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: reason === "unreachable" ? "This tab lost its connection to Grain." : "Grain is running. Reconnect this browser tab." }),
|
|
14341
14364
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Run this command in your terminal to open your workspace again:" }),
|
|
14342
14365
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth-action", children: [
|
|
14343
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-web-reauth-command", children: "grain
|
|
14366
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-web-reauth-command", children: "grain ui" }),
|
|
14344
14367
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14345
14368
|
"button",
|
|
14346
14369
|
{
|
|
14347
14370
|
type: "button",
|
|
14348
14371
|
className: "sp-web-secondary-button",
|
|
14349
14372
|
onClick: () => void copyCommand(),
|
|
14350
|
-
"aria-label": "Copy grain
|
|
14373
|
+
"aria-label": "Copy grain ui",
|
|
14351
14374
|
children: copied ? "Copied" : "Copy"
|
|
14352
14375
|
}
|
|
14353
14376
|
)
|
|
14354
14377
|
] }),
|
|
14355
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-detail", children: reason === "expired-link" ? "This link has expired or was already used." : reason === "unreachable" ? "Grain may have restarted
|
|
14378
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-detail", children: reason === "expired-link" ? "This link has expired or was already used." : reason === "unreachable" ? "Grain may have stopped, or restarted on a different port. If it stopped, start it again first." : "This tab needs a fresh workspace link." })
|
|
14356
14379
|
] });
|
|
14357
14380
|
}
|
|
14358
14381
|
function isUpdateMarkerStatus(value) {
|
|
@@ -14472,7 +14495,10 @@ function fieldVisible(field, values) {
|
|
|
14472
14495
|
function ConnectionSetupPage({
|
|
14473
14496
|
onDone,
|
|
14474
14497
|
onCancel,
|
|
14475
|
-
initialConnection
|
|
14498
|
+
initialConnection,
|
|
14499
|
+
actions: actions2,
|
|
14500
|
+
mode = "full",
|
|
14501
|
+
canEditDetails = false
|
|
14476
14502
|
}) {
|
|
14477
14503
|
const { callServerTool, isReady } = useHostContext();
|
|
14478
14504
|
const [connectors, setConnectors] = reactExports.useState([]);
|
|
@@ -14489,20 +14515,20 @@ function ConnectionSetupPage({
|
|
|
14489
14515
|
initialConnection?.["id"] ?? `conn_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
14490
14516
|
)
|
|
14491
14517
|
);
|
|
14518
|
+
const [displayMode, setDisplayMode] = reactExports.useState(mode);
|
|
14492
14519
|
reactExports.useEffect(() => {
|
|
14493
|
-
if (!isReady) {
|
|
14520
|
+
if (!actions2 && !isReady) {
|
|
14494
14521
|
return;
|
|
14495
14522
|
}
|
|
14496
14523
|
let active = true;
|
|
14497
|
-
void callServerTool("list_connectors", {}).then((result) => {
|
|
14524
|
+
void (actions2 ? actions2.listConnectors() : callServerTool("list_connectors", {}).then((result) => {
|
|
14525
|
+
if (result.isError) throw new Error(toolMessage(result));
|
|
14526
|
+
return JSON.parse(toolMessage(result));
|
|
14527
|
+
})).then((result) => {
|
|
14498
14528
|
if (!active) {
|
|
14499
14529
|
return;
|
|
14500
14530
|
}
|
|
14501
|
-
|
|
14502
|
-
throw new Error(toolMessage(result));
|
|
14503
|
-
}
|
|
14504
|
-
const text = toolMessage(result);
|
|
14505
|
-
const listed = JSON.parse(text);
|
|
14531
|
+
const listed = result;
|
|
14506
14532
|
if (!Array.isArray(listed)) {
|
|
14507
14533
|
throw new Error("Connector list is unavailable.");
|
|
14508
14534
|
}
|
|
@@ -14524,7 +14550,7 @@ function ConnectionSetupPage({
|
|
|
14524
14550
|
return () => {
|
|
14525
14551
|
active = false;
|
|
14526
14552
|
};
|
|
14527
|
-
}, [callServerTool, isReady, initialConnection]);
|
|
14553
|
+
}, [callServerTool, isReady, initialConnection, actions2]);
|
|
14528
14554
|
const selected = connectors.find((connector) => connector.id === type);
|
|
14529
14555
|
const properties = selected?.schema?.properties ?? {};
|
|
14530
14556
|
const entries = Object.entries(properties).filter(([key, field]) => {
|
|
@@ -14549,6 +14575,11 @@ function ConnectionSetupPage({
|
|
|
14549
14575
|
...Object.fromEntries(entries.map(([key, field]) => [key, values[key] ?? field.default]))
|
|
14550
14576
|
});
|
|
14551
14577
|
const test = async () => {
|
|
14578
|
+
if (actions2) {
|
|
14579
|
+
await actions2.test(profile(), password || void 0);
|
|
14580
|
+
setTested(true);
|
|
14581
|
+
return true;
|
|
14582
|
+
}
|
|
14552
14583
|
const result = await callServerTool(
|
|
14553
14584
|
"test_connection",
|
|
14554
14585
|
initialConnection && !password ? { connectionId: draftId } : { type, connectionProfile: { ...profile(), ...password ? { password } : {} } }
|
|
@@ -14573,6 +14604,12 @@ function ConnectionSetupPage({
|
|
|
14573
14604
|
return;
|
|
14574
14605
|
}
|
|
14575
14606
|
const id = draftId;
|
|
14607
|
+
if (actions2) {
|
|
14608
|
+
await actions2.save(profile(), password || void 0);
|
|
14609
|
+
setPassword("");
|
|
14610
|
+
onDone(id);
|
|
14611
|
+
return;
|
|
14612
|
+
}
|
|
14576
14613
|
const saved = await callServerTool("save_connection", {
|
|
14577
14614
|
connectionProfile: { ...profile(), id }
|
|
14578
14615
|
});
|
|
@@ -14649,8 +14686,8 @@ function ConnectionSetupPage({
|
|
|
14649
14686
|
};
|
|
14650
14687
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "grain-connection-page", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-content", children: [
|
|
14651
14688
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-intro", children: [
|
|
14652
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: initialConnection ? "Edit connection" : "Connect a database" }),
|
|
14653
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Add a connection to start querying your data." })
|
|
14689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: actions2 ? "Finish connection setup" : initialConnection ? "Edit connection" : "Connect a database" }),
|
|
14690
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: actions2 ? "Test and save this connection to continue." : "Add a connection to start querying your data." })
|
|
14654
14691
|
] }),
|
|
14655
14692
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
14656
14693
|
error && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-error", role: "alert", children: [
|
|
@@ -14668,7 +14705,7 @@ function ConnectionSetupPage({
|
|
|
14668
14705
|
value: type,
|
|
14669
14706
|
onChange: (event) => selectType(event.target.value),
|
|
14670
14707
|
required: true,
|
|
14671
|
-
disabled: !isReady || busy !== null,
|
|
14708
|
+
disabled: (actions2 ? true : !isReady) || busy !== null,
|
|
14672
14709
|
children: [
|
|
14673
14710
|
!type && /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Choose a database" }),
|
|
14674
14711
|
connectors.map((connector) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connector.id, children: connector.displayName }, connector.id))
|
|
@@ -14685,20 +14722,36 @@ function ConnectionSetupPage({
|
|
|
14685
14722
|
value: name,
|
|
14686
14723
|
onChange: (event) => setName(event.target.value),
|
|
14687
14724
|
placeholder: "e.g. Analytics",
|
|
14688
|
-
required: true
|
|
14725
|
+
required: true,
|
|
14726
|
+
readOnly: Boolean(actions2)
|
|
14689
14727
|
}
|
|
14690
14728
|
)
|
|
14691
14729
|
] })
|
|
14692
14730
|
] }),
|
|
14731
|
+
displayMode === "password" && canEditDetails && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14732
|
+
"button",
|
|
14733
|
+
{
|
|
14734
|
+
type: "button",
|
|
14735
|
+
className: "grain-connection-secondary grain-connection-edit",
|
|
14736
|
+
onClick: () => setDisplayMode("full"),
|
|
14737
|
+
children: "Edit details"
|
|
14738
|
+
}
|
|
14739
|
+
),
|
|
14693
14740
|
selected && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
14694
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14741
|
+
displayMode === "full" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14695
14742
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Connection details" }),
|
|
14696
14743
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: entries.filter(([, field]) => !field.ui?.advanced).map(renderField) })
|
|
14744
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14745
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Connection details" }),
|
|
14746
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dl", { className: "grain-connection-readonly", children: entries.map(([key, field]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
14747
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dt", { children: field.title ?? key }),
|
|
14748
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dd", { children: String(values[key] ?? field.default ?? "") })
|
|
14749
|
+
] }, key)) })
|
|
14697
14750
|
] }),
|
|
14698
|
-
passwordField && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14751
|
+
(passwordField || actions2 && displayMode === "password") && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "grain-connection-section", children: [
|
|
14699
14752
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Authentication" }),
|
|
14700
14753
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-field", children: [
|
|
14701
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-password", children: passwordField
|
|
14754
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "grain-connection-password", children: passwordField?.title ?? "Password" }),
|
|
14702
14755
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-password", children: [
|
|
14703
14756
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14704
14757
|
"input",
|
|
@@ -14723,7 +14776,7 @@ function ConnectionSetupPage({
|
|
|
14723
14776
|
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: "Stored on this computer after connecting." })
|
|
14724
14777
|
] }) })
|
|
14725
14778
|
] }),
|
|
14726
|
-
entries.some(([, field]) => field.ui?.advanced) && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "grain-connection-advanced", children: [
|
|
14779
|
+
displayMode === "full" && entries.some(([, field]) => field.ui?.advanced) && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "grain-connection-advanced", children: [
|
|
14727
14780
|
/* @__PURE__ */ jsxRuntimeExports.jsx("summary", { children: "Advanced settings" }),
|
|
14728
14781
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grain-connection-grid", children: entries.filter(([, field]) => field.ui?.advanced).map(renderField) })
|
|
14729
14782
|
] })
|
|
@@ -75059,6 +75112,10 @@ const DENSITY_HEIGHTS = {
|
|
|
75059
75112
|
normal: { row: 35, header: 42 },
|
|
75060
75113
|
comfortable: { row: 45, header: 52 }
|
|
75061
75114
|
};
|
|
75115
|
+
const NUMERIC_TYPE = /^(unsigned\s+|signed\s+)?(u?(tiny|small|medium|big|huge)?int(eger)?\d*|decimal|numeric|number|double|float\d*|real|long|short|byte|money)(\s+(precision|unsigned|signed))?\s*(\(\s*\d+\s*(,\s*\d+\s*)?\))?$/i;
|
|
75116
|
+
function isNumericColumnType(type) {
|
|
75117
|
+
return Boolean(type && NUMERIC_TYPE.test(type.trim()));
|
|
75118
|
+
}
|
|
75062
75119
|
const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
75063
75120
|
theme: theme2,
|
|
75064
75121
|
data,
|
|
@@ -75068,6 +75125,7 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75068
75125
|
nativeTheme = false,
|
|
75069
75126
|
disableFilters = false,
|
|
75070
75127
|
autoSizeStrategy,
|
|
75128
|
+
fillWidth = false,
|
|
75071
75129
|
onCellDoubleClick
|
|
75072
75130
|
}, ref) {
|
|
75073
75131
|
const trackUi = useTrackUi();
|
|
@@ -75236,6 +75294,21 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75236
75294
|
}),
|
|
75237
75295
|
[data, getNodeValue, copyIncludesHeaders]
|
|
75238
75296
|
);
|
|
75297
|
+
const userResizedRef = reactExports.useRef(false);
|
|
75298
|
+
const fillSpareWidth = reactExports.useCallback((e2) => {
|
|
75299
|
+
if (userResizedRef.current) return;
|
|
75300
|
+
const body = e2.api.getHorizontalPixelRange?.();
|
|
75301
|
+
const columns = (e2.api.getAllDisplayedColumns?.() ?? []).filter((c) => !c.getPinned());
|
|
75302
|
+
if (!body || columns.length === 0) return;
|
|
75303
|
+
const used = columns.reduce((sum2, c) => sum2 + c.getActualWidth(), 0);
|
|
75304
|
+
if (used < body.right - body.left) e2.api.sizeColumnsToFit();
|
|
75305
|
+
}, []);
|
|
75306
|
+
const noteUserResize = reactExports.useCallback((e2) => {
|
|
75307
|
+
if (e2.source === "uiColumnResized" && e2.finished) userResizedRef.current = true;
|
|
75308
|
+
}, []);
|
|
75309
|
+
reactExports.useEffect(() => {
|
|
75310
|
+
userResizedRef.current = false;
|
|
75311
|
+
}, [data?.columns]);
|
|
75239
75312
|
const columnDefs = reactExports.useMemo(() => {
|
|
75240
75313
|
if (!data?.columns) return [];
|
|
75241
75314
|
const isInRange = (rowIndex, displayedColIndex) => {
|
|
@@ -75293,6 +75366,7 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75293
75366
|
return p.data[col.name];
|
|
75294
75367
|
return void 0;
|
|
75295
75368
|
},
|
|
75369
|
+
...isNumericColumnType(col.type) ? { cellClass: "sp-num-cell", headerClass: "ag-right-aligned-header" } : {},
|
|
75296
75370
|
cellClassRules: {
|
|
75297
75371
|
"sp-range-cell": (p) => isInRange(p.rowIndex ?? 0, index + 1)
|
|
75298
75372
|
},
|
|
@@ -75419,6 +75493,11 @@ const DataGrid = reactExports.forwardRef(function DataGrid2({
|
|
|
75419
75493
|
onGridReady: (p) => {
|
|
75420
75494
|
apiRef.current = p.api;
|
|
75421
75495
|
},
|
|
75496
|
+
...fillWidth ? {
|
|
75497
|
+
onFirstDataRendered: fillSpareWidth,
|
|
75498
|
+
onGridSizeChanged: fillSpareWidth,
|
|
75499
|
+
onColumnResized: noteUserResize
|
|
75500
|
+
} : {},
|
|
75422
75501
|
rowData: data.rows,
|
|
75423
75502
|
columnDefs,
|
|
75424
75503
|
defaultColDef: {
|
|
@@ -149247,6 +149326,7 @@ function getFormInitialData(connection) {
|
|
|
149247
149326
|
delete formData["type"];
|
|
149248
149327
|
delete formData["builtIn"];
|
|
149249
149328
|
delete formData["hasPassword"];
|
|
149329
|
+
delete formData["draft"];
|
|
149250
149330
|
return formData;
|
|
149251
149331
|
}
|
|
149252
149332
|
function schemaHasPasswordField(schema) {
|
|
@@ -149285,9 +149365,10 @@ function schemaForConnectionMode(schema, connectorId, mode) {
|
|
|
149285
149365
|
}
|
|
149286
149366
|
};
|
|
149287
149367
|
}
|
|
149368
|
+
const UNREACHABLE_MESSAGE = "Can't reach Grain. Start Grain and try again.";
|
|
149288
149369
|
const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
149289
149370
|
const { callServerTool, isReady, mode, sendMessage, onMessage } = useHostContext();
|
|
149290
|
-
const
|
|
149371
|
+
const grainServiceSetup = useAppStore((state) => state.grainServiceSetup);
|
|
149291
149372
|
const supportsActiveConnection = mode === "vscode";
|
|
149292
149373
|
const trackUi = useTrackUi();
|
|
149293
149374
|
reactExports.useEffect(() => {
|
|
@@ -149519,7 +149600,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149519
149600
|
const profileToSave = {
|
|
149520
149601
|
...formData,
|
|
149521
149602
|
type: typeToSave,
|
|
149522
|
-
id: connection?.id ?? `conn_${Date.now()}
|
|
149603
|
+
id: connection?.id ?? `conn_${Date.now()}`,
|
|
149604
|
+
...connection?.draft ? { draft: false } : {}
|
|
149523
149605
|
};
|
|
149524
149606
|
if (isEditing2 && profileToSave["password"] === "") {
|
|
149525
149607
|
delete profileToSave["password"];
|
|
@@ -149795,10 +149877,30 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149795
149877
|
}
|
|
149796
149878
|
return null;
|
|
149797
149879
|
};
|
|
149880
|
+
const renderUnreachableActions = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: 12, display: "flex", gap: 8 }, children: [
|
|
149881
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }),
|
|
149882
|
+
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149883
|
+
"button",
|
|
149884
|
+
{
|
|
149885
|
+
className: "sp-btn",
|
|
149886
|
+
onClick: () => sendMessage?.(grainServiceSetup === "not-set-up" ? "setUpGrain" : "startGrain"),
|
|
149887
|
+
children: grainServiceSetup === "not-set-up" ? "Set up Grain" : "Start Grain"
|
|
149888
|
+
}
|
|
149889
|
+
)
|
|
149890
|
+
] });
|
|
149891
|
+
const renderUnreachableState = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", children: [
|
|
149892
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: UNREACHABLE_MESSAGE }),
|
|
149893
|
+
renderUnreachableActions()
|
|
149894
|
+
] });
|
|
149798
149895
|
const renderConnectionForm = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-detail", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-detail-body", children: [
|
|
149799
149896
|
renderToast(),
|
|
149800
|
-
!selectedType &&
|
|
149801
|
-
!selectedType &&
|
|
149897
|
+
!selectedType && connectors.length === 0 && connectionsUnreachable && renderUnreachableState(),
|
|
149898
|
+
!selectedType && connectors.length === 0 && !connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", children: [
|
|
149899
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "No database types are available." }),
|
|
149900
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }) })
|
|
149901
|
+
] }),
|
|
149902
|
+
!selectedType && connectors.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-section", children: "Database Type" }),
|
|
149903
|
+
!selectedType && connectors.length > 0 && ["local", "server"].map((group) => {
|
|
149802
149904
|
const groupConnectors = connectors.filter((c) => getConnectorGroup(c.id) === group);
|
|
149803
149905
|
if (groupConnectors.length === 0) {
|
|
149804
149906
|
return null;
|
|
@@ -149975,11 +150077,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
149975
150077
|
gap: "12px"
|
|
149976
150078
|
},
|
|
149977
150079
|
children: connections.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", style: { gridColumn: "1 / -1" }, children: [
|
|
149978
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ?
|
|
149979
|
-
connectionsUnreachable &&
|
|
149980
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }),
|
|
149981
|
-
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: () => sendMessage?.("startGrain"), children: grainServiceInstalled ? "Start Grain" : "Set up Grain" })
|
|
149982
|
-
] }),
|
|
150080
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ? UNREACHABLE_MESSAGE : "No connections configured." }),
|
|
150081
|
+
connectionsUnreachable && renderUnreachableActions(),
|
|
149983
150082
|
mode === "vscode" && !connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149984
150083
|
"button",
|
|
149985
150084
|
{
|
|
@@ -150056,7 +150155,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
150056
150155
|
},
|
|
150057
150156
|
children: [
|
|
150058
150157
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `sp-dot sp-dot-${status}` }),
|
|
150059
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--sp-muted-fg)" }, children: statusLabel }),
|
|
150158
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--sp-muted-fg)" }, children: c.draft ? "Needs setup" : statusLabel }),
|
|
150159
|
+
c.draft && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-pill", children: "Draft" }),
|
|
150060
150160
|
isActive && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-pill", style: { marginLeft: "auto" }, children: "Active" })
|
|
150061
150161
|
]
|
|
150062
150162
|
}
|
|
@@ -150080,7 +150180,8 @@ const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
|
150080
150180
|
meta: selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150081
150181
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-badge", children: selectedConnection.type }),
|
|
150082
150182
|
supportsActiveConnection && activeConnectionId === selectedConnection.id && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-active-badge", children: "Active" }),
|
|
150083
|
-
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" })
|
|
150183
|
+
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" }),
|
|
150184
|
+
selectedConnection.draft && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Draft" })
|
|
150084
150185
|
] }),
|
|
150085
150186
|
actions: isFormOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", onClick: closeForm, "aria-label": "Cancel", children: "Cancel" }) : selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150086
150187
|
supportsActiveConnection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -150251,6 +150352,10 @@ const TOOL_ENTRIES = {
|
|
|
150251
150352
|
list_connections: ["connections", "Show saved connection profiles."],
|
|
150252
150353
|
get_demo_dataset: ["connections", "Offer the built-in bookstore demo data and sample queries."],
|
|
150253
150354
|
save_connection: ["connections", "Create or update a connection profile."],
|
|
150355
|
+
create_connection_draft: [
|
|
150356
|
+
"connections",
|
|
150357
|
+
"Create a draft connection and give the user a setup link."
|
|
150358
|
+
],
|
|
150254
150359
|
request_connection_credentials: ["connections", "Ask the user to enter a connection password."],
|
|
150255
150360
|
test_connection: ["connections", "Verify a saved or draft profile."],
|
|
150256
150361
|
delete_connection: ["connections", "Remove a saved profile."],
|
|
@@ -150758,13 +150863,13 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
150758
150863
|
title: "This daemon can run standalone or inside VS Code; check the releases page for the latest version.",
|
|
150759
150864
|
children: "View Releases"
|
|
150760
150865
|
}
|
|
150761
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150866
|
+
) : updateAvailable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150762
150867
|
"button",
|
|
150763
150868
|
{
|
|
150764
150869
|
type: "button",
|
|
150765
150870
|
className: "sp-btn",
|
|
150766
150871
|
onClick: () => sendMessage("openExtensionPage", {}),
|
|
150767
|
-
children:
|
|
150872
|
+
children: "Open Update"
|
|
150768
150873
|
}
|
|
150769
150874
|
)
|
|
150770
150875
|
] }),
|
|
@@ -151423,7 +151528,7 @@ const LandingScreen = ({
|
|
|
151423
151528
|
activeConnectionName: storeConnName,
|
|
151424
151529
|
activeConnectorType: storeConnType,
|
|
151425
151530
|
openSettingsPanel,
|
|
151426
|
-
|
|
151531
|
+
grainServiceSetup
|
|
151427
151532
|
} = useAppStore();
|
|
151428
151533
|
const [fetchedConnName, setFetchedConnName] = reactExports.useState(null);
|
|
151429
151534
|
const [fetchedConnType, setFetchedConnType] = reactExports.useState(null);
|
|
@@ -151498,9 +151603,13 @@ const LandingScreen = ({
|
|
|
151498
151603
|
] }),
|
|
151499
151604
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-landing-subtitle", children: "Execute SQL queries directly in your IDE." })
|
|
151500
151605
|
] }),
|
|
151501
|
-
|
|
151502
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children:
|
|
151503
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("
|
|
151606
|
+
grainServiceSetup === "not-set-up" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-active-connection", children: [
|
|
151607
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Grain's background service isn't set up. Set it up once so your agents and the grain CLI can reach Grain when VS Code is closed." }),
|
|
151608
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("setUpGrain"), children: "Set up Grain" })
|
|
151609
|
+
] }),
|
|
151610
|
+
grainServiceSetup !== "not-set-up" && !hasActiveConnection && grainUnavailable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-active-connection", children: [
|
|
151611
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: grainServiceSetup === "registered" ? "Grain is stopped. Start Grain to see your connections." : "Grain starts when needed on this machine." }),
|
|
151612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("startGrain"), children: "Start Grain" })
|
|
151504
151613
|
] }),
|
|
151505
151614
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151506
151615
|
"div",
|
|
@@ -151630,7 +151739,7 @@ function SafeModeIndicator({
|
|
|
151630
151739
|
capability
|
|
151631
151740
|
] });
|
|
151632
151741
|
}
|
|
151633
|
-
function MultiTabLayout({ emptyState } = {}) {
|
|
151742
|
+
function MultiTabLayout({ emptyState, fillGridWidth = false } = {}) {
|
|
151634
151743
|
const {
|
|
151635
151744
|
tabs,
|
|
151636
151745
|
activeTabId,
|
|
@@ -152319,6 +152428,7 @@ ${activeTab.errorDetails}` : activeTab.error;
|
|
|
152319
152428
|
data: activeTab.result,
|
|
152320
152429
|
copyIncludesHeaders,
|
|
152321
152430
|
density: rowDensity,
|
|
152431
|
+
fillWidth: fillGridWidth,
|
|
152322
152432
|
onCellDoubleClick: handleCellDoubleClick
|
|
152323
152433
|
}
|
|
152324
152434
|
)
|
|
@@ -152332,6 +152442,7 @@ ${activeTab.errorDetails}` : activeTab.error;
|
|
|
152332
152442
|
data: activeTab.result,
|
|
152333
152443
|
copyIncludesHeaders,
|
|
152334
152444
|
density: rowDensity,
|
|
152445
|
+
fillWidth: fillGridWidth,
|
|
152335
152446
|
onCellDoubleClick: handleCellDoubleClick
|
|
152336
152447
|
}
|
|
152337
152448
|
),
|
|
@@ -152393,6 +152504,60 @@ ${activeTab.errorDetails}` : activeTab.error ?? "",
|
|
|
152393
152504
|
)
|
|
152394
152505
|
] });
|
|
152395
152506
|
}
|
|
152507
|
+
function SidebarAddButton({ label, title, onClick }) {
|
|
152508
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152509
|
+
"button",
|
|
152510
|
+
{
|
|
152511
|
+
type: "button",
|
|
152512
|
+
className: "sp-web-section-add",
|
|
152513
|
+
onClick,
|
|
152514
|
+
title,
|
|
152515
|
+
"aria-label": label,
|
|
152516
|
+
children: "+"
|
|
152517
|
+
}
|
|
152518
|
+
);
|
|
152519
|
+
}
|
|
152520
|
+
function SqlEditor({ value, onChange, onRun }) {
|
|
152521
|
+
const frameRef = reactExports.useRef(null);
|
|
152522
|
+
const gutterRef = reactExports.useRef(null);
|
|
152523
|
+
const lineCount = value.split("\n").length;
|
|
152524
|
+
const digits = Math.max(2, String(lineCount).length);
|
|
152525
|
+
reactExports.useLayoutEffect(() => {
|
|
152526
|
+
frameRef.current?.style.setProperty("--sp-web-gutter-digits", String(digits));
|
|
152527
|
+
}, [digits]);
|
|
152528
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: frameRef, className: "sp-web-sql-editor-frame", children: [
|
|
152529
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152530
|
+
"div",
|
|
152531
|
+
{
|
|
152532
|
+
ref: gutterRef,
|
|
152533
|
+
className: "sp-web-sql-gutter",
|
|
152534
|
+
"aria-hidden": "true",
|
|
152535
|
+
"data-testid": "sql-gutter",
|
|
152536
|
+
children: Array.from({ length: lineCount }, (_, index) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: index + 1 }, index))
|
|
152537
|
+
}
|
|
152538
|
+
),
|
|
152539
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152540
|
+
"textarea",
|
|
152541
|
+
{
|
|
152542
|
+
className: "sp-web-sql-editor",
|
|
152543
|
+
"aria-label": "SQL editor",
|
|
152544
|
+
spellCheck: false,
|
|
152545
|
+
wrap: "off",
|
|
152546
|
+
value,
|
|
152547
|
+
onChange: (event) => onChange(event.target.value),
|
|
152548
|
+
onScroll: (event) => {
|
|
152549
|
+
if (gutterRef.current) gutterRef.current.scrollTop = event.currentTarget.scrollTop;
|
|
152550
|
+
},
|
|
152551
|
+
onKeyDown: (event) => {
|
|
152552
|
+
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
152553
|
+
event.preventDefault();
|
|
152554
|
+
onRun();
|
|
152555
|
+
}
|
|
152556
|
+
}
|
|
152557
|
+
}
|
|
152558
|
+
)
|
|
152559
|
+
] });
|
|
152560
|
+
}
|
|
152396
152561
|
const THEME_KEY = "grain:web-theme";
|
|
152397
152562
|
const SIDEBAR_DEFAULT_WIDTH = 220;
|
|
152398
152563
|
const SIDEBAR_MIN_WIDTH = 160;
|
|
@@ -152495,14 +152660,15 @@ function WebApp({ viewHint }) {
|
|
|
152495
152660
|
};
|
|
152496
152661
|
const runQuery = async () => {
|
|
152497
152662
|
if (!activeTab || !activeTab.sql.trim() || !selectedConnectionId || activeTab.isLoading) return;
|
|
152498
|
-
const { id, sql } = activeTab;
|
|
152663
|
+
const { id, sql, title } = activeTab;
|
|
152499
152664
|
updateTab(id, { isLoading: true, error: null, cancelled: false });
|
|
152500
152665
|
try {
|
|
152501
152666
|
const result = await callServerTool("run_query", {
|
|
152502
152667
|
sql,
|
|
152503
152668
|
session: WEB_SESSION_ID,
|
|
152504
152669
|
tabId: activeTab.remoteId,
|
|
152505
|
-
connectionId: selectedConnectionId
|
|
152670
|
+
connectionId: selectedConnectionId,
|
|
152671
|
+
title
|
|
152506
152672
|
});
|
|
152507
152673
|
const data = result.structuredContent;
|
|
152508
152674
|
if (useAppStore.getState().tabs.find((tab) => tab.id === id)?.cancelled) return;
|
|
@@ -152869,6 +153035,14 @@ function WebApp({ viewHint }) {
|
|
|
152869
153035
|
monitorOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { ref: sidebarRef, className: "sp-web-sidebar", "aria-label": "Workspace navigation", children: [
|
|
152870
153036
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-header", children: [
|
|
152871
153037
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-sidebar-title", children: "Connections" }),
|
|
153038
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153039
|
+
SidebarAddButton,
|
|
153040
|
+
{
|
|
153041
|
+
label: "Add connection",
|
|
153042
|
+
title: "Add connection",
|
|
153043
|
+
onClick: () => setSetupOpen(true)
|
|
153044
|
+
}
|
|
153045
|
+
),
|
|
152872
153046
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152873
153047
|
"button",
|
|
152874
153048
|
{
|
|
@@ -152877,7 +153051,7 @@ function WebApp({ viewHint }) {
|
|
|
152877
153051
|
onClick: () => setMonitorOpen(false),
|
|
152878
153052
|
title: "Hide sidebar",
|
|
152879
153053
|
"aria-label": "Hide sidebar",
|
|
152880
|
-
children:
|
|
153054
|
+
children: "«"
|
|
152881
153055
|
}
|
|
152882
153056
|
)
|
|
152883
153057
|
] }),
|
|
@@ -152894,36 +153068,31 @@ function WebApp({ viewHint }) {
|
|
|
152894
153068
|
"aria-valuemax": SIDEBAR_MAX_WIDTH
|
|
152895
153069
|
}
|
|
152896
153070
|
),
|
|
152897
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
152898
|
-
|
|
152899
|
-
|
|
152900
|
-
|
|
152901
|
-
|
|
152902
|
-
|
|
152903
|
-
|
|
152904
|
-
children:
|
|
152905
|
-
|
|
152906
|
-
|
|
152907
|
-
|
|
152908
|
-
|
|
152909
|
-
|
|
152910
|
-
|
|
152911
|
-
|
|
152912
|
-
|
|
152913
|
-
|
|
152914
|
-
|
|
152915
|
-
|
|
152916
|
-
|
|
152917
|
-
|
|
152918
|
-
|
|
152919
|
-
|
|
152920
|
-
children: "+ Add connection"
|
|
152921
|
-
}
|
|
152922
|
-
)
|
|
153071
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-connection-list", children: connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153072
|
+
"button",
|
|
153073
|
+
{
|
|
153074
|
+
type: "button",
|
|
153075
|
+
className: "sp-web-connection-item",
|
|
153076
|
+
onClick: () => openConnection(connection.id),
|
|
153077
|
+
children: [
|
|
153078
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DatabaseIcon, { size: 15 }) }),
|
|
153079
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-web-connection-label", children: [
|
|
153080
|
+
connection.name ?? connection.id,
|
|
153081
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: connection.type })
|
|
153082
|
+
] }),
|
|
153083
|
+
connection.engineState === "ready" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153084
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-dot", "aria-hidden": "true" }),
|
|
153085
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-visually-hidden", children: "Ready" })
|
|
153086
|
+
] })
|
|
153087
|
+
]
|
|
153088
|
+
},
|
|
153089
|
+
connection.id
|
|
153090
|
+
)) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-sidebar-helper", children: "No connections yet." }) }),
|
|
153091
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-sidebar-section-title", children: [
|
|
153092
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Queries" }),
|
|
153093
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarAddButton, { label: "Add query", title: "New query", onClick: () => newQuery() })
|
|
152923
153094
|
] }),
|
|
152924
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-section-title", children: "Queries" }),
|
|
152925
153095
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-session-list", children: [
|
|
152926
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: () => newQuery(), children: "+ New query" }),
|
|
152927
153096
|
closedQueries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: reopenQuery, children: "Reopen closed query" }),
|
|
152928
153097
|
tabs.filter((tab) => tab.sessionId === WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152929
153098
|
"button",
|
|
@@ -153141,21 +153310,18 @@ function WebApp({ viewHint }) {
|
|
|
153141
153310
|
)
|
|
153142
153311
|
] }),
|
|
153143
153312
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-toolbar", children: [
|
|
153144
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
153145
|
-
|
|
153146
|
-
|
|
153147
|
-
"
|
|
153148
|
-
|
|
153149
|
-
|
|
153150
|
-
|
|
153151
|
-
|
|
153152
|
-
|
|
153153
|
-
|
|
153154
|
-
|
|
153155
|
-
|
|
153156
|
-
}
|
|
153157
|
-
)
|
|
153158
|
-
] }),
|
|
153313
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153314
|
+
"select",
|
|
153315
|
+
{
|
|
153316
|
+
"aria-label": "Query connection",
|
|
153317
|
+
value: selectedConnectionId,
|
|
153318
|
+
onChange: (event) => setQueryConnections((current2) => ({
|
|
153319
|
+
...current2,
|
|
153320
|
+
[activeTab.id]: event.target.value
|
|
153321
|
+
})),
|
|
153322
|
+
children: connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connection.id, children: connection.name ?? connection.id }, connection.id))
|
|
153323
|
+
}
|
|
153324
|
+
) }),
|
|
153159
153325
|
activeTab.isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153160
153326
|
"button",
|
|
153161
153327
|
{
|
|
@@ -153172,6 +153338,7 @@ function WebApp({ viewHint }) {
|
|
|
153172
153338
|
onClick: () => void runQuery(),
|
|
153173
153339
|
disabled: !selectedConnectionId || !activeTab.sql.trim(),
|
|
153174
153340
|
children: [
|
|
153341
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-run-glyph", "aria-hidden": "true", children: "▶" }),
|
|
153175
153342
|
"Run ",
|
|
153176
153343
|
/* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "⌘↵" })
|
|
153177
153344
|
]
|
|
@@ -153179,25 +153346,16 @@ function WebApp({ viewHint }) {
|
|
|
153179
153346
|
)
|
|
153180
153347
|
] }),
|
|
153181
153348
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153182
|
-
|
|
153349
|
+
SqlEditor,
|
|
153183
153350
|
{
|
|
153184
|
-
className: "sp-web-sql-editor",
|
|
153185
|
-
"aria-label": "SQL editor",
|
|
153186
|
-
spellCheck: false,
|
|
153187
153351
|
value: activeTab.sql,
|
|
153188
|
-
onChange: (
|
|
153189
|
-
|
|
153190
|
-
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
153191
|
-
event.preventDefault();
|
|
153192
|
-
void runQuery();
|
|
153193
|
-
}
|
|
153194
|
-
}
|
|
153352
|
+
onChange: (sql) => updateTab(activeTab.id, { sql }),
|
|
153353
|
+
onRun: () => void runQuery()
|
|
153195
153354
|
}
|
|
153196
153355
|
)
|
|
153197
|
-
] })
|
|
153198
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results-label", children: "Results" })
|
|
153356
|
+
] })
|
|
153199
153357
|
] }),
|
|
153200
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", hidden: Boolean(activeConnectionId), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState }) })
|
|
153358
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", hidden: Boolean(activeConnectionId), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState, fillGridWidth: true }) })
|
|
153201
153359
|
] })
|
|
153202
153360
|
] })
|
|
153203
153361
|
] });
|
|
@@ -163150,6 +163308,12 @@ body.vscode-high-contrast .ag-theme-quartz {
|
|
|
163150
163308
|
outline: none !important;
|
|
163151
163309
|
}
|
|
163152
163310
|
|
|
163311
|
+
.sp-num-cell {
|
|
163312
|
+
justify-content: flex-end;
|
|
163313
|
+
text-align: right;
|
|
163314
|
+
font-variant-numeric: tabular-nums;
|
|
163315
|
+
}
|
|
163316
|
+
|
|
163153
163317
|
.sp-null {
|
|
163154
163318
|
color: var(--sp-muted-fg);
|
|
163155
163319
|
font-style: italic;
|
|
@@ -166216,10 +166380,54 @@ body {
|
|
|
166216
166380
|
letter-spacing: 0;
|
|
166217
166381
|
}
|
|
166218
166382
|
.sp-web-sidebar-section-title {
|
|
166219
|
-
|
|
166220
|
-
|
|
166383
|
+
display: flex;
|
|
166384
|
+
align-items: center;
|
|
166385
|
+
justify-content: space-between;
|
|
166386
|
+
margin: 18px 0 6px;
|
|
166387
|
+
padding: 17px 9px 0;
|
|
166221
166388
|
border-top: 1px solid var(--grain-border-subtle);
|
|
166222
166389
|
}
|
|
166390
|
+
.sp-web-sidebar-header .sp-web-sidebar-title {
|
|
166391
|
+
flex: 1;
|
|
166392
|
+
}
|
|
166393
|
+
.sp-web-section-add,
|
|
166394
|
+
.sp-web-sidebar-close {
|
|
166395
|
+
display: inline-flex;
|
|
166396
|
+
align-items: center;
|
|
166397
|
+
justify-content: center;
|
|
166398
|
+
width: 22px;
|
|
166399
|
+
height: 22px;
|
|
166400
|
+
padding: 0;
|
|
166401
|
+
border: 0;
|
|
166402
|
+
border-radius: var(--grain-radius-sm);
|
|
166403
|
+
background: transparent;
|
|
166404
|
+
color: var(--grain-ink-muted);
|
|
166405
|
+
font: 400 16px/1 var(--grain-font-body);
|
|
166406
|
+
cursor: pointer;
|
|
166407
|
+
}
|
|
166408
|
+
.sp-web-sidebar-close {
|
|
166409
|
+
font-size: 13px;
|
|
166410
|
+
}
|
|
166411
|
+
.sp-web-section-add:hover,
|
|
166412
|
+
.sp-web-sidebar-close:hover {
|
|
166413
|
+
background: var(--grain-surface-raised);
|
|
166414
|
+
color: var(--grain-ink);
|
|
166415
|
+
}
|
|
166416
|
+
.sp-web-section-add:focus-visible,
|
|
166417
|
+
.sp-web-sidebar-close:focus-visible {
|
|
166418
|
+
outline: 1px solid var(--grain-accent);
|
|
166419
|
+
}
|
|
166420
|
+
.sp-web-connection-label {
|
|
166421
|
+
flex: 1;
|
|
166422
|
+
min-width: 0;
|
|
166423
|
+
}
|
|
166424
|
+
.sp-web-connection-dot {
|
|
166425
|
+
width: 7px;
|
|
166426
|
+
height: 7px;
|
|
166427
|
+
flex: none;
|
|
166428
|
+
border-radius: 50%;
|
|
166429
|
+
background: var(--sp-success);
|
|
166430
|
+
}
|
|
166223
166431
|
.sp-web-connection-item {
|
|
166224
166432
|
display: flex;
|
|
166225
166433
|
align-items: center;
|
|
@@ -166338,7 +166546,7 @@ body {
|
|
|
166338
166546
|
.sp-web-query-tabs {
|
|
166339
166547
|
display: flex;
|
|
166340
166548
|
align-items: stretch;
|
|
166341
|
-
min-height:
|
|
166549
|
+
min-height: 42px;
|
|
166342
166550
|
overflow-x: auto;
|
|
166343
166551
|
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166344
166552
|
background: var(--grain-surface);
|
|
@@ -166352,6 +166560,9 @@ body {
|
|
|
166352
166560
|
background: var(--grain-ground);
|
|
166353
166561
|
box-shadow: inset 0 -2px var(--grain-accent);
|
|
166354
166562
|
}
|
|
166563
|
+
.sp-web-query-tab.active button:first-child {
|
|
166564
|
+
color: var(--grain-accent);
|
|
166565
|
+
}
|
|
166355
166566
|
.sp-web-query-tab button,
|
|
166356
166567
|
.sp-web-query-tab-action {
|
|
166357
166568
|
border: 0;
|
|
@@ -166359,7 +166570,7 @@ body {
|
|
|
166359
166570
|
color: var(--grain-ink);
|
|
166360
166571
|
font: inherit;
|
|
166361
166572
|
cursor: pointer;
|
|
166362
|
-
padding: 8px
|
|
166573
|
+
padding: 8px 14px;
|
|
166363
166574
|
white-space: nowrap;
|
|
166364
166575
|
}
|
|
166365
166576
|
.sp-web-query-tab button:last-child {
|
|
@@ -166375,7 +166586,7 @@ body {
|
|
|
166375
166586
|
width: 100%;
|
|
166376
166587
|
padding: 0;
|
|
166377
166588
|
border: 0;
|
|
166378
|
-
resize:
|
|
166589
|
+
resize: none;
|
|
166379
166590
|
background: transparent;
|
|
166380
166591
|
color: var(--grain-ink);
|
|
166381
166592
|
font-family: var(--grain-font-body);
|
|
@@ -166434,26 +166645,43 @@ body {
|
|
|
166434
166645
|
opacity: 0.5;
|
|
166435
166646
|
cursor: default;
|
|
166436
166647
|
}
|
|
166648
|
+
.sp-web-sql-editor-frame {
|
|
166649
|
+
--sp-web-gutter-width: calc(var(--sp-web-gutter-digits, 2) * 1ch + 28px);
|
|
166650
|
+
position: relative;
|
|
166651
|
+
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166652
|
+
background: var(--grain-ground);
|
|
166653
|
+
}
|
|
166654
|
+
.sp-web-sql-gutter {
|
|
166655
|
+
position: absolute;
|
|
166656
|
+
top: 0;
|
|
166657
|
+
bottom: 0;
|
|
166658
|
+
left: 0;
|
|
166659
|
+
box-sizing: border-box;
|
|
166660
|
+
width: var(--sp-web-gutter-width);
|
|
166661
|
+
overflow: hidden;
|
|
166662
|
+
padding: 20px 12px 40px 0;
|
|
166663
|
+
border-right: 1px solid var(--grain-border-subtle);
|
|
166664
|
+
color: var(--grain-ink-muted);
|
|
166665
|
+
font: 12px/1.7 var(--grain-font-mono);
|
|
166666
|
+
text-align: right;
|
|
166667
|
+
user-select: none;
|
|
166668
|
+
}
|
|
166437
166669
|
.sp-web-sql-editor {
|
|
166438
166670
|
display: block;
|
|
166439
166671
|
box-sizing: border-box;
|
|
166440
|
-
width: 100
|
|
166672
|
+
width: calc(100% - var(--sp-web-gutter-width));
|
|
166441
166673
|
min-height: 190px;
|
|
166442
|
-
|
|
166674
|
+
margin-left: var(--sp-web-gutter-width);
|
|
166675
|
+
padding: 20px 24px 20px 16px;
|
|
166443
166676
|
border: 0;
|
|
166444
|
-
border-bottom: 1px solid var(--grain-border-subtle);
|
|
166445
166677
|
resize: vertical;
|
|
166678
|
+
white-space: pre;
|
|
166446
166679
|
outline-color: var(--grain-accent);
|
|
166447
166680
|
background: var(--grain-ground);
|
|
166448
166681
|
color: var(--grain-ink);
|
|
166449
166682
|
font: 12px/1.7 var(--grain-font-mono);
|
|
166450
166683
|
tab-size: 2;
|
|
166451
166684
|
}
|
|
166452
|
-
.sp-web-results-label {
|
|
166453
|
-
padding: 10px 24px;
|
|
166454
|
-
font-size: 12px;
|
|
166455
|
-
font-weight: 700;
|
|
166456
|
-
}
|
|
166457
166685
|
.sp-web-results {
|
|
166458
166686
|
display: flex;
|
|
166459
166687
|
flex: 1;
|
|
@@ -166480,6 +166708,15 @@ body {
|
|
|
166480
166708
|
font-weight: 700;
|
|
166481
166709
|
}
|
|
166482
166710
|
|
|
166711
|
+
.sp-web-run-glyph {
|
|
166712
|
+
margin-right: 6px;
|
|
166713
|
+
font-size: 9px;
|
|
166714
|
+
}
|
|
166715
|
+
.sp-web-query-toolbar > .sp-web-primary-button {
|
|
166716
|
+
display: inline-flex;
|
|
166717
|
+
align-items: center;
|
|
166718
|
+
font-weight: 600;
|
|
166719
|
+
}
|
|
166483
166720
|
.sp-web-query-toolbar kbd {
|
|
166484
166721
|
margin-left: 6px;
|
|
166485
166722
|
padding: 2px 5px;
|
|
@@ -166545,6 +166782,8 @@ body {
|
|
|
166545
166782
|
.sp-web-connection-item:hover,
|
|
166546
166783
|
.sp-web-connection-item:focus-visible {
|
|
166547
166784
|
background: var(--grain-surface);
|
|
166785
|
+
}
|
|
166786
|
+
.sp-web-connection-item:focus-visible {
|
|
166548
166787
|
outline: 1px solid var(--grain-accent);
|
|
166549
166788
|
}
|
|
166550
166789
|
.sp-web-connection-detail {
|