diff --git a/src/extensions/notebook/notebook-block-code.tsx b/src/extensions/notebook/notebook-block-code.tsx
index 5b97dcca..e9eaeb8f 100644
--- a/src/extensions/notebook/notebook-block-code.tsx
+++ b/src/extensions/notebook/notebook-block-code.tsx
@@ -3,12 +3,21 @@ import { NotebookEditorBlockValue } from "./notebook-editor";
import { NotebookVM } from "./notebook-vm";
import JavascriptEditor from "@/components/editor/javascript-editor";
import { Button } from "@/components/ui/button";
-import { LucideShieldAlert, PlayIcon, Terminal } from "lucide-react";
+import {
+ LucideLoader,
+ LucideShieldAlert,
+ LucideTerminal,
+ PlayIcon,
+ Terminal,
+} from "lucide-react";
import { produce } from "immer";
import { cn } from "@/lib/utils";
-interface OutputFormat {
- type: "log";
+export interface NotebookOutputFormat {
+ id?: string;
+ type: "log" | "error" | "query";
+ sql?: string;
+ queryStatus?: "running" | "success" | "error";
args: unknown[];
}
@@ -42,25 +51,53 @@ function OutputArgItem({ value }: { value: unknown }) {
return {content};
}
-function OutputItem({ value }: { value: OutputFormat }) {
- const color = value.type === "log" ? "" : "text-red-400 dark:text-red-300";
+function OutputItem({ value }: { value: NotebookOutputFormat }) {
+ if (value.type === "query") {
+ let icon = ;
+ let color = "";
- return (
-
- {value.type === "log" ? (
-
- ) : (
+ if (value.queryStatus === "success") {
+ icon =
;
+ color = "text-green-600 dark:text-green-400";
+ } else if (value.queryStatus === "error") {
+ icon =
;
+ color = "text-red-400 dark:text-red-300";
+ }
+
+ return (
+
+
{icon}
+
+ ⬤
+ {value.sql}
+
+
+ );
+ } else if (value.type === "error") {
+ return (
+
- )}
-
- {value.args.map((argValue, argIndex) => (
-
- ))}
-
-
- );
+
+ {value.args.map((argValue, argIndex) => (
+
+ ))}
+
+
+ );
+ } else {
+ return (
+
+
+
+ {value.args.map((argValue, argIndex) => (
+
+ ))}
+
+
+ );
+ }
}
export default function NotebookBlockCode({
@@ -72,7 +109,7 @@ export default function NotebookBlockCode({
value: NotebookEditorBlockValue;
onChange: (value: NotebookEditorBlockValue) => void;
}) {
- const [output, setOutput] = useState([]);
+ const [output, setOutput] = useState([]);
const onRunClick = () => {
setOutput([]);
@@ -80,11 +117,12 @@ export default function NotebookBlockCode({
complete: () => {
console.log("Complete");
},
- stdOut: (data: any) => {
- setOutput((prev) => [...prev, data]);
- },
- stdErr: () => {
- console.log("Error");
+ stdOut: (data) => {
+ if (data.id) {
+ setOutput((prev) => [...prev.filter((p) => p.id !== data.id), data]);
+ } else {
+ setOutput((prev) => [...prev, data]);
+ }
},
});
};
diff --git a/src/extensions/notebook/notebook-editor.tsx b/src/extensions/notebook/notebook-editor.tsx
index 3b824bd1..2d8f98f6 100644
--- a/src/extensions/notebook/notebook-editor.tsx
+++ b/src/extensions/notebook/notebook-editor.tsx
@@ -47,7 +47,7 @@ export default function NotebookEditor() {
value: `for(let i = 0; i < 5; i++) {
await sleep(1000);
const age = Math.floor(Math.random() * 100));
- const name = "name \${i}";
+ const name = \`name \${i}\`;
await query(\`INSERT INTO testing(name, age) VALUES ('\${name}', \${age})\`);
console.log("Inserting", name, age);
}`,
diff --git a/src/extensions/notebook/notebook-vm.tsx b/src/extensions/notebook/notebook-vm.tsx
index 33f90485..448d5ee7 100644
--- a/src/extensions/notebook/notebook-vm.tsx
+++ b/src/extensions/notebook/notebook-vm.tsx
@@ -1,5 +1,6 @@
import { BaseDriver } from "@/drivers/base-driver";
import { useEffect, useMemo } from "react";
+import { NotebookOutputFormat } from "./notebook-block-code";
const workerCode = `
let scope = {};
@@ -52,16 +53,14 @@ const workerCode = `
interface RunOpions {
complete?: () => void;
- stdOut?: (data: T) => void;
- stdErr?: () => void;
+ stdOut?: (data: NotebookOutputFormat) => void;
}
export class NotebookVM {
protected vm: Worker;
protected driver: BaseDriver;
protected onComplete?: () => void;
- protected onStdOut?: (data: T) => void;
- protected onStdErr?: () => void;
+ protected onStdOut?: (data: NotebookOutputFormat) => void;
constructor(vm: Worker, driver: BaseDriver) {
this.vm = vm;
@@ -71,21 +70,25 @@ export class NotebookVM {
const { type } = e.data;
if (type === "log" || type === "error") {
- if (this.onStdOut) {
- this.onStdOut(e.data);
- }
+ if (this.onStdOut) this.onStdOut(e.data);
} else if (type === "query") {
+ if (this.onStdOut) this.onStdOut({ ...e.data, queryStatus: "running" });
+
this.driver
.query(e.data.sql)
.then((result) => {
- console.log("Got it result", result);
this.vm.postMessage({
type: "query_result",
id: e.data.id,
result: result,
});
+ if (this.onStdOut)
+ this.onStdOut({ ...e.data, queryStatus: "success" });
})
.catch((error) => {
+ if (this.onStdOut)
+ this.onStdOut({ ...e.data, queryStatus: "error" });
+
if (error instanceof Error) {
this.vm.postMessage({
type: "query_result",
@@ -111,7 +114,6 @@ export class NotebookVM {
run(code: string, options: RunOpions): void {
this.onComplete = options.complete;
this.onStdOut = options.stdOut;
- this.onStdErr = options.stdErr;
this.vm.postMessage({
type: "eval",