diff --git a/src/lib/components/Console.svelte b/src/lib/components/Console.svelte
new file mode 100644
index 0000000..3bc3595
--- /dev/null
+++ b/src/lib/components/Console.svelte
@@ -0,0 +1,104 @@
+
+
+
+
+
+ {#each logs as log}
+
+ {log.timestamp.toUTCString()}
+ {log.data}
+
+ {/each}
+
+
+
+
diff --git a/src/lib/components/Editor/theme.ts b/src/lib/components/Editor/theme.ts
index d417787..b5f544d 100644
--- a/src/lib/components/Editor/theme.ts
+++ b/src/lib/components/Editor/theme.ts
@@ -36,6 +36,6 @@ export const theme = syntaxHighlighting(
{ tag: t.heading, fontWeight: 'bold', color: 'hsl(220deg 2% 90%)' },
{ tag: [t.atom, t.bool], color: 'hsl(45, 7%, 75%)' },
{ tag: [t.processingInstruction, t.string, t.inserted], color: 'hsl(41, 37%, 68%)' },
- { tag: t.invalid, color: '#ff008c' }
+ { tag: t.invalid, color: 'hsl(327deg 100% 50%)' }
])
);
diff --git a/src/lib/components/Result.svelte b/src/lib/components/Result.svelte
index 9323540..4c5b6bb 100644
--- a/src/lib/components/Result.svelte
+++ b/src/lib/components/Result.svelte
@@ -3,14 +3,17 @@
import type { OLAPResponse } from '$lib/olap-engine';
import { untrack } from 'svelte';
import ChartContainer from './ChartContainer.svelte';
+ import Console, { type Log } from './Console.svelte';
interface Props {
response?: OLAPResponse;
+ logs?: Log[];
+ tab?: 'data' | 'chart' | 'logs';
+ onClearLogs?: () => void;
}
- let { response }: Props = $props();
+ let { response, logs = [], tab = $bindable('data'), onClearLogs }: Props = $props();
- let tab = $state<'data' | 'chart'>('data');
let yAxis = $state('');
let xAxis = $state('');
let chartType = $state('line');
@@ -27,6 +30,7 @@
{#if response}
@@ -36,6 +40,10 @@
{/if}
{/if}
+
+ {#if tab === 'logs'}
+
+ {/if}
diff --git a/src/lib/icons/Trash.svelte b/src/lib/icons/Trash.svelte
new file mode 100644
index 0000000..b3944d0
--- /dev/null
+++ b/src/lib/icons/Trash.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/olap-engine/Logger.ts b/src/lib/olap-engine/Logger.ts
new file mode 100644
index 0000000..694bc9a
--- /dev/null
+++ b/src/lib/olap-engine/Logger.ts
@@ -0,0 +1,25 @@
+type Callback = (param: any) => void;
+
+export interface ILogger {
+ on(level: 'error', fn: Callback): () => void;
+ log(level: 'error', param: any): void;
+}
+
+export abstract class Logger implements ILogger {
+ #listeners: { [key: string]: Set } = {};
+
+ on(logEvent: 'error', fn: Callback) {
+ this.#listeners[logEvent] ??= new Set();
+
+ this.#listeners[logEvent].add(fn);
+ return () => this.#listeners[logEvent].delete(fn);
+ }
+
+ log(level: 'error', param: any) {
+ if (!this.#listeners[level]?.size) return;
+
+ queueMicrotask(() => {
+ for (const fn of this.#listeners[level]) fn(param);
+ });
+ }
+}
diff --git a/src/lib/olap-engine/engine-chdb.ts b/src/lib/olap-engine/engine-chdb.ts
index 556ee4b..198ee3d 100644
--- a/src/lib/olap-engine/engine-chdb.ts
+++ b/src/lib/olap-engine/engine-chdb.ts
@@ -1,10 +1,11 @@
import { invoke } from '@tauri-apps/api/core';
-import type { OLAPEngine, Table, OLAPResponse } from './index';
+import type { OLAPEngine, OLAPResponse, Table } from './index';
+import { Logger } from './Logger';
import CLICKHOUSE_GET_SCHEMA from './queries/clickhouse_get_schema.sql?raw';
import CLICKHOUSE_INIT_DB from './queries/clickhouse_init_db.sql?raw';
-export class CHDBEngine implements OLAPEngine {
+export class CHDBEngine extends Logger implements OLAPEngine {
async init() {
await this.exec(CLICKHOUSE_INIT_DB);
}
@@ -16,8 +17,9 @@ export class CHDBEngine implements OLAPEngine {
return JSON.parse(r) as OLAPResponse;
} catch (e) {
+ if (typeof e === 'string') e = new Error(e);
console.error(e);
- return undefined;
+ this.log('error', e);
}
}
diff --git a/src/lib/olap-engine/engine-remote.ts b/src/lib/olap-engine/engine-remote.ts
index 570f75f..d70fc48 100644
--- a/src/lib/olap-engine/engine-remote.ts
+++ b/src/lib/olap-engine/engine-remote.ts
@@ -1,28 +1,30 @@
-import type { OLAPEngine, Table, OLAPResponse } from './index';
+import type { OLAPEngine, OLAPResponse, Table } from './index';
+import { Logger } from './Logger';
import CLICKHOUSE_GET_SCHEMA from './queries/clickhouse_get_schema.sql?raw';
-export class RemoteEngine implements OLAPEngine {
+export class RemoteEngine extends Logger implements OLAPEngine {
async init() {}
async exec(query: string) {
try {
const proxy =
new URLSearchParams(window.location.search).get('proxy') ?? 'https://proxy.agx.app/query';
- const response = await fetch(`${proxy}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: query
- });
- const r = await response.text();
- if (!r) return;
+ const response = await fetch(proxy, { method: 'POST', body: query });
- return JSON.parse(r) as OLAPResponse;
+ if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
+
+ const r = await response.text();
+ if (!r) throw new Error(`Empty Response`);
+
+ const data: RemoteEngineResponse = JSON.parse(r);
+
+ if ('exception' in data) throw new Error(data.exception);
+
+ return data;
} catch (e) {
console.error(e);
- return undefined;
+ this.log('error', e);
}
}
@@ -32,3 +34,12 @@ export class RemoteEngine implements OLAPEngine {
return response.data as Table[];
}
}
+
+interface RemoteEngineException {
+ meta: [];
+ data: [];
+ rows: 0;
+ exception: string;
+}
+
+type RemoteEngineResponse = OLAPResponse | RemoteEngineException;
diff --git a/src/lib/olap-engine/index.ts b/src/lib/olap-engine/index.ts
index 5dfc6a6..8540334 100644
--- a/src/lib/olap-engine/index.ts
+++ b/src/lib/olap-engine/index.ts
@@ -1,9 +1,16 @@
import { CHDBEngine } from './engine-chdb';
import { RemoteEngine } from './engine-remote';
+import type { ILogger } from './Logger';
export type OLAPResponse = {
meta: Array;
data: Array<{ [key: string]: any }>;
+ rows: number;
+ statistics: {
+ bytes_read: number;
+ elapsed: number;
+ rows_read: number;
+ };
};
export interface ColumnDescriptor {
@@ -17,7 +24,7 @@ export interface Table {
columns: ColumnDescriptor[];
}
-export interface OLAPEngine {
+export interface OLAPEngine extends ILogger {
init(): Promise;
exec(query: string): Promise;
getSchema(): Promise;
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 389290b..c9f35f7 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,4 +1,5 @@
@@ -299,7 +313,12 @@
{/snippet}
{#snippet b()}
-
+ (errors = [])}
+ />
{/snippet}
{/snippet}