mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
Three of these were not branding at all — they were live breakage, because the server was renamed and its consumers were not: - dashboard.html parsed `ClickHouseAsyncMetrics_` while PrometheusMetricsWriter emits `DatastoreAsyncMetrics_`. Paste the Prometheus output into the metrics editor and it matched nothing. - trace-visualizer queried `attribute['clickhouse.thread_id']` while OpenTelemetryTraceContext records `datastore.thread_id`. The trace tab found no spans. - both visualizers loaded `js/query-clickhouse.js`; the file on disk is `query-datastore.js`, so the script 404'd and the query function never existed. The rest is the name: titles, navbar brands, the status line a user reads after connecting, links into upstream's repo and docs site, their Cloud badges, and tests-visualizer pulling a logo from their CDN and querying their public demo server. Local symbols and DOM ids went with them (queryDatastore, parseDatastoreTrace, #tabDatastore). LICENSE, NOTICE and every copyright notice are untouched — no removed line in this diff carries a ©, an SPDX id or an attribution. `clickhouse_lexer_*` in docs.html STAYS, and a comment at the embed site says why: those export names are baked into the base64 WebAssembly payload, so the JS must match the blob. Renaming means renaming the C API, rebuilding Lexer.wasm, re-embedding it and updating the calls in one change; rename either side alone and syntax highlighting fails silently. Co-authored-by: Hanzo Dev <[email protected]>
73 lines
2.4 KiB
JavaScript
73 lines
2.4 KiB
JavaScript
let add_http_cors_header = (location.protocol != 'file:');
|
|
|
|
async function queryDatastore({host, user, password, query, is_stopping, for_each_row, on_error, controller}) {
|
|
// Construct URL
|
|
let url = `${host}?default_format=JSONEachRow&enable_http_compression=1`
|
|
if (add_http_cors_header)
|
|
// For debug purposes, you may set add_http_cors_header from the browser console
|
|
url += '&add_http_cors_header=1';
|
|
if (user)
|
|
url += `&user=${encodeURIComponent(user)}`;
|
|
if (password)
|
|
url += `&password=${encodeURIComponent(password)}`;
|
|
|
|
console.log("QUERY", query);
|
|
|
|
let response, reply, error;
|
|
try {
|
|
// Send the query
|
|
response = await fetch(url, {
|
|
method: "POST",
|
|
body: query,
|
|
signal: controller.signal,
|
|
headers: { 'Authorization': 'never' }
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const reply = await response.text();
|
|
console.log(reply);
|
|
for (line of reply.split('\n')) {
|
|
if (line.startsWith(`{"exception":`)) {
|
|
throw new Error(`HTTP Status: ${response.status}. Error: ${JSON.parse(line).exception}`);
|
|
}
|
|
}
|
|
throw new Error(`HTTP Status: ${response.status}. Error: ${reply.toString()}`);
|
|
}
|
|
|
|
// Initiate stream processing of response body
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
|
|
// Read data row by row
|
|
let buffer = '';
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done)
|
|
break;
|
|
if (is_stopping && is_stopping())
|
|
break;
|
|
|
|
buffer += decoder.decode(value, { stream: true });
|
|
let lines = buffer.split('\n');
|
|
for (const line of lines.slice(0, -1)) {
|
|
if (is_stopping && is_stopping())
|
|
break;
|
|
const data = JSON.parse(line);
|
|
await for_each_row(data);
|
|
}
|
|
buffer = lines[lines.length - 1];
|
|
}
|
|
} catch (e) {
|
|
console.log("CLICKHOUSE QUERY FAILED", e);
|
|
if (on_error) {
|
|
if (e instanceof TypeError) {
|
|
on_error("Network error");
|
|
} else if (e.name === 'AbortError') {
|
|
on_error("Query was cancelled");
|
|
} else {
|
|
on_error(e.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|