@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.js
CHANGED
|
@@ -57,6 +57,7 @@ function useAIAnalyst(options) {
|
|
|
57
57
|
}, [storageKey]);
|
|
58
58
|
const [conversation, setConversation] = useState(() => loadFromStorage());
|
|
59
59
|
const [schemas, setSchemas] = useState(/* @__PURE__ */ new Map());
|
|
60
|
+
const [allSchemas, setAllSchemas] = useState([]);
|
|
60
61
|
const [isLoading, setIsLoading] = useState(false);
|
|
61
62
|
const [error, setError] = useState(null);
|
|
62
63
|
const [lastLoadedData, setLastLoadedData] = useState(null);
|
|
@@ -78,6 +79,34 @@ function useAIAnalyst(options) {
|
|
|
78
79
|
);
|
|
79
80
|
const messages = conversation.messages;
|
|
80
81
|
const hasMessages = conversation.messages.length > 0;
|
|
82
|
+
const fetchAllSchemas = useCallback(async () => {
|
|
83
|
+
if (!configRef.current.endpoint)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
const response = await fetch(configRef.current.endpoint, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify({ action: "get-all-schemas" })
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`Failed to fetch all schemas: ${response.statusText}`);
|
|
93
|
+
}
|
|
94
|
+
const data = await response.json();
|
|
95
|
+
if (data.error) {
|
|
96
|
+
throw new Error(data.error);
|
|
97
|
+
}
|
|
98
|
+
setAllSchemas(data.schemas);
|
|
99
|
+
setSchemas((prev) => {
|
|
100
|
+
const newMap = new Map(prev);
|
|
101
|
+
for (const schema of data.schemas) {
|
|
102
|
+
newMap.set(schema.table, schema);
|
|
103
|
+
}
|
|
104
|
+
return newMap;
|
|
105
|
+
});
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.warn("[TinyPivot] Failed to fetch all schemas:", err);
|
|
108
|
+
}
|
|
109
|
+
}, []);
|
|
81
110
|
const fetchTables = useCallback(async () => {
|
|
82
111
|
if (!configRef.current.endpoint)
|
|
83
112
|
return;
|
|
@@ -102,6 +131,7 @@ function useAIAnalyst(options) {
|
|
|
102
131
|
// Capitalize
|
|
103
132
|
description: t.description
|
|
104
133
|
})));
|
|
134
|
+
await fetchAllSchemas();
|
|
105
135
|
} catch (err) {
|
|
106
136
|
console.warn("[TinyPivot] Failed to fetch tables:", err);
|
|
107
137
|
onError?.({
|
|
@@ -111,7 +141,7 @@ function useAIAnalyst(options) {
|
|
|
111
141
|
} finally {
|
|
112
142
|
setIsLoadingTables(false);
|
|
113
143
|
}
|
|
114
|
-
}, [onError]);
|
|
144
|
+
}, [onError, fetchAllSchemas]);
|
|
115
145
|
useEffect(() => {
|
|
116
146
|
if (configRef.current.endpoint && (!config.dataSources || config.dataSources.length === 0)) {
|
|
117
147
|
fetchTables();
|
|
@@ -143,6 +173,40 @@ function useAIAnalyst(options) {
|
|
|
143
173
|
console.warn("Failed to fetch schema:", err);
|
|
144
174
|
}
|
|
145
175
|
}, []);
|
|
176
|
+
const fetchSampleData = useCallback(async (dataSource) => {
|
|
177
|
+
if (!configRef.current.endpoint)
|
|
178
|
+
return;
|
|
179
|
+
try {
|
|
180
|
+
const sql = `SELECT * FROM ${dataSource.table} LIMIT 100`;
|
|
181
|
+
const response = await fetch(configRef.current.endpoint, {
|
|
182
|
+
method: "POST",
|
|
183
|
+
headers: { "Content-Type": "application/json" },
|
|
184
|
+
body: JSON.stringify({
|
|
185
|
+
action: "query",
|
|
186
|
+
sql,
|
|
187
|
+
table: dataSource.table
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
throw new Error(`Failed to fetch sample data: ${response.statusText}`);
|
|
192
|
+
}
|
|
193
|
+
const result = await response.json();
|
|
194
|
+
if (result.error) {
|
|
195
|
+
throw new Error(result.error);
|
|
196
|
+
}
|
|
197
|
+
if (result.data && result.data.length > 0) {
|
|
198
|
+
setLastLoadedData(result.data);
|
|
199
|
+
onDataLoaded?.({
|
|
200
|
+
data: result.data,
|
|
201
|
+
query: sql,
|
|
202
|
+
dataSourceId: dataSource.id,
|
|
203
|
+
rowCount: result.data.length
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
console.warn("Failed to fetch sample data:", err);
|
|
208
|
+
}
|
|
209
|
+
}, [onDataLoaded]);
|
|
146
210
|
const selectDataSource = useCallback(async (dataSourceId) => {
|
|
147
211
|
const dataSource = effectiveDataSources.find((ds) => ds.id === dataSourceId);
|
|
148
212
|
if (!dataSource) {
|
|
@@ -197,9 +261,10 @@ What would you like to know about this data?`
|
|
|
197
261
|
}
|
|
198
262
|
} else if (configRef.current.endpoint) {
|
|
199
263
|
await fetchSchema(dataSource);
|
|
264
|
+
await fetchSampleData(dataSource);
|
|
200
265
|
}
|
|
201
|
-
}, [effectiveDataSources, fetchSchema, onConversationUpdate, onDataLoaded]);
|
|
202
|
-
const callAIEndpoint = useCallback(async (userInput, currentConversation, currentSchemas, currentDataSources) => {
|
|
266
|
+
}, [effectiveDataSources, fetchSchema, fetchSampleData, onConversationUpdate, onDataLoaded]);
|
|
267
|
+
const callAIEndpoint = useCallback(async (userInput, currentConversation, currentSchemas, currentDataSources, currentAllSchemas) => {
|
|
203
268
|
if (!configRef.current.endpoint) {
|
|
204
269
|
throw new Error("No endpoint configured. Set `endpoint` in AI analyst config.");
|
|
205
270
|
}
|
|
@@ -207,7 +272,8 @@ What would you like to know about this data?`
|
|
|
207
272
|
const systemPrompt = buildSystemPrompt(
|
|
208
273
|
currentDataSources,
|
|
209
274
|
currentSchemas,
|
|
210
|
-
dataSourceId
|
|
275
|
+
dataSourceId,
|
|
276
|
+
currentAllSchemas.length > 0 ? currentAllSchemas : void 0
|
|
211
277
|
);
|
|
212
278
|
const apiMessages = getMessagesForAPI(currentConversation);
|
|
213
279
|
const messages2 = [
|
|
@@ -466,7 +532,7 @@ What would you like to know about this data?`
|
|
|
466
532
|
});
|
|
467
533
|
return;
|
|
468
534
|
}
|
|
469
|
-
const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources);
|
|
535
|
+
const aiResponse = await callAIEndpoint(content, currentConv, schemas, effectiveDataSources, allSchemas);
|
|
470
536
|
const sqlQuery = extractSQLFromResponse(aiResponse);
|
|
471
537
|
if (sqlQuery) {
|
|
472
538
|
const validation = validateSQLSafety(sqlQuery);
|