@smallwebco/tinypivot-react 1.0.60 → 1.0.62
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/index.cjs +71 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -5
- package/dist/index.js.map +1 -1
- package/dist/style.css +1302 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -101,6 +101,7 @@ function useAIAnalyst(options) {
|
|
|
101
101
|
}, [storageKey]);
|
|
102
102
|
const [conversation, setConversation] = (0, import_react.useState)(() => loadFromStorage());
|
|
103
103
|
const [schemas, setSchemas] = (0, import_react.useState)(/* @__PURE__ */ new Map());
|
|
104
|
+
const [allSchemas, setAllSchemas] = (0, import_react.useState)([]);
|
|
104
105
|
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
105
106
|
const [error, setError] = (0, import_react.useState)(null);
|
|
106
107
|
const [lastLoadedData, setLastLoadedData] = (0, import_react.useState)(null);
|
|
@@ -122,6 +123,34 @@ function useAIAnalyst(options) {
|
|
|
122
123
|
);
|
|
123
124
|
const messages = conversation.messages;
|
|
124
125
|
const hasMessages = conversation.messages.length > 0;
|
|
126
|
+
const fetchAllSchemas = (0, import_react.useCallback)(async () => {
|
|
127
|
+
if (!configRef.current.endpoint)
|
|
128
|
+
return;
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch(configRef.current.endpoint, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: { "Content-Type": "application/json" },
|
|
133
|
+
body: JSON.stringify({ action: "get-all-schemas" })
|
|
134
|
+
});
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
throw new Error(`Failed to fetch all schemas: ${response.statusText}`);
|
|
137
|
+
}
|
|
138
|
+
const data = await response.json();
|
|
139
|
+
if (data.error) {
|
|
140
|
+
throw new Error(data.error);
|
|
141
|
+
}
|
|
142
|
+
setAllSchemas(data.schemas);
|
|
143
|
+
setSchemas((prev) => {
|
|
144
|
+
const newMap = new Map(prev);
|
|
145
|
+
for (const schema of data.schemas) {
|
|
146
|
+
newMap.set(schema.table, schema);
|
|
147
|
+
}
|
|
148
|
+
return newMap;
|
|
149
|
+
});
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.warn("[TinyPivot] Failed to fetch all schemas:", err);
|
|
152
|
+
}
|
|
153
|
+
}, []);
|
|
125
154
|
const fetchTables = (0, import_react.useCallback)(async () => {
|
|
126
155
|
if (!configRef.current.endpoint)
|
|
127
156
|
return;
|
|
@@ -146,6 +175,7 @@ function useAIAnalyst(options) {
|
|
|
146
175
|
// Capitalize
|
|
147
176
|
description: t.description
|
|
148
177
|
})));
|
|
178
|
+
await fetchAllSchemas();
|
|
149
179
|
} catch (err) {
|
|
150
180
|
console.warn("[TinyPivot] Failed to fetch tables:", err);
|
|
151
181
|
onError?.({
|
|
@@ -155,7 +185,7 @@ function useAIAnalyst(options) {
|
|
|
155
185
|
} finally {
|
|
156
186
|
setIsLoadingTables(false);
|
|
157
187
|
}
|
|
158
|
-
}, [onError]);
|
|
188
|
+
}, [onError, fetchAllSchemas]);
|
|
159
189
|
(0, import_react.useEffect)(() => {
|
|
160
190
|
if (configRef.current.endpoint && (!config.dataSources || config.dataSources.length === 0)) {
|
|
161
191
|
fetchTables();
|
|
@@ -187,6 +217,40 @@ function useAIAnalyst(options) {
|
|
|
187
217
|
console.warn("Failed to fetch schema:", err);
|
|
188
218
|
}
|
|
189
219
|
}, []);
|
|
220
|
+
const fetchSampleData = (0, import_react.useCallback)(async (dataSource) => {
|
|
221
|
+
if (!configRef.current.endpoint)
|
|
222
|
+
return;
|
|
223
|
+
try {
|
|
224
|
+
const sql = `SELECT * FROM ${dataSource.table} LIMIT 100`;
|
|
225
|
+
const response = await fetch(configRef.current.endpoint, {
|
|
226
|
+
method: "POST",
|
|
227
|
+
headers: { "Content-Type": "application/json" },
|
|
228
|
+
body: JSON.stringify({
|
|
229
|
+
action: "query",
|
|
230
|
+
sql,
|
|
231
|
+
table: dataSource.table
|
|
232
|
+
})
|
|
233
|
+
});
|
|
234
|
+
if (!response.ok) {
|
|
235
|
+
throw new Error(`Failed to fetch sample data: ${response.statusText}`);
|
|
236
|
+
}
|
|
237
|
+
const result = await response.json();
|
|
238
|
+
if (result.error) {
|
|
239
|
+
throw new Error(result.error);
|
|
240
|
+
}
|
|
241
|
+
if (result.data && result.data.length > 0) {
|
|
242
|
+
setLastLoadedData(result.data);
|
|
243
|
+
onDataLoaded?.({
|
|
244
|
+
data: result.data,
|
|
245
|
+
query: sql,
|
|
246
|
+
dataSourceId: dataSource.id,
|
|
247
|
+
rowCount: result.data.length
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
} catch (err) {
|
|
251
|
+
console.warn("Failed to fetch sample data:", err);
|
|
252
|
+
}
|
|
253
|
+
}, [onDataLoaded]);
|
|
190
254
|
const selectDataSource = (0, import_react.useCallback)(async (dataSourceId) => {
|
|
191
255
|
const dataSource = effectiveDataSources.find((ds) => ds.id === dataSourceId);
|
|
192
256
|
if (!dataSource) {
|
|
@@ -241,9 +305,10 @@ What would you like to know about this data?`
|
|
|
241
305
|
}
|
|
242
306
|
} else if (configRef.current.endpoint) {
|
|
243
307
|
await fetchSchema(dataSource);
|
|
308
|
+
await fetchSampleData(dataSource);
|
|
244
309
|
}
|
|
245
|
-
}, [effectiveDataSources, fetchSchema, onConversationUpdate, onDataLoaded]);
|
|
246
|
-
const callAIEndpoint = (0, import_react.useCallback)(async (userInput, currentConversation, currentSchemas, currentDataSources) => {
|
|
310
|
+
}, [effectiveDataSources, fetchSchema, fetchSampleData, onConversationUpdate, onDataLoaded]);
|
|
311
|
+
const callAIEndpoint = (0, import_react.useCallback)(async (userInput, currentConversation, currentSchemas, currentDataSources, currentAllSchemas) => {
|
|
247
312
|
if (!configRef.current.endpoint) {
|
|
248
313
|
throw new Error("No endpoint configured. Set `endpoint` in AI analyst config.");
|
|
249
314
|
}
|
|
@@ -251,7 +316,8 @@ What would you like to know about this data?`
|
|
|
251
316
|
const systemPrompt = (0, import_tinypivot_core.buildSystemPrompt)(
|
|
252
317
|
currentDataSources,
|
|
253
318
|
currentSchemas,
|
|
254
|
-
dataSourceId
|
|
319
|
+
dataSourceId,
|
|
320
|
+
currentAllSchemas.length > 0 ? currentAllSchemas : void 0
|
|
255
321
|
);
|
|
256
322
|
const apiMessages = (0, import_tinypivot_core.getMessagesForAPI)(currentConversation);
|
|
257
323
|
const messages2 = [
|
|
@@ -510,7 +576,7 @@ What would you like to know about this data?`
|
|
|
510
576
|
});
|
|
511
577
|
return;
|
|
512
578
|
}
|
|
513
|
-
const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources);
|
|
579
|
+
const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources, allSchemas);
|
|
514
580
|
const sqlQuery = (0, import_tinypivot_core.extractSQLFromResponse)(aiResponse);
|
|
515
581
|
if (sqlQuery) {
|
|
516
582
|
const validation = (0, import_tinypivot_core.validateSQLSafety)(sqlQuery);
|