Files
zeekayandHanzo Dev e53ccdf6d5 the pages call the server this fork actually is
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]>
2026-08-14 10:17:16 -07:00

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());
}
}
}
}