From 0768e0fb07d965af6622ecd6f1b550b3caf9a051 Mon Sep 17 00:00:00 2001
From: osdodo <osdodo@qq.com>
Date: Fri, 2 Jun 2023 12:35:20 +0800
Subject: [PATCH 1/2] improve db table module

---
 src/components/IDE/DBTable/DBTable.tsx    |  98 +++++-----
 src/components/IDE/DBTable/SideBar.tsx    |  45 +----
 src/components/IDE/DBTable/index.tsx      |  10 +-
 src/store/lib/w3bstream/schema/dbTable.ts | 216 +++++++++++-----------
 src/store/standard/PromiseState.ts        |  14 +-
 5 files changed, 182 insertions(+), 201 deletions(-)

diff --git a/src/components/IDE/DBTable/DBTable.tsx b/src/components/IDE/DBTable/DBTable.tsx
index e9c64e63..3dec6983 100644
--- a/src/components/IDE/DBTable/DBTable.tsx
+++ b/src/components/IDE/DBTable/DBTable.tsx
@@ -1,8 +1,8 @@
 import { observer } from 'mobx-react-lite';
 import { useStore } from '@/store/index';
-import { Box, Button, Flex, Stack, Image } from '@chakra-ui/react';
+import { Box, Button, Flex, Stack, Image, Spinner, Text } from '@chakra-ui/react';
 import JSONTable from '@/components/JSONTable';
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useRef } from 'react';
 import { defaultButtonStyle, defaultOutlineButtonStyle } from '@/lib/theme';
 import { MdRefresh } from 'react-icons/md';
 import { AddIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
@@ -190,6 +190,38 @@ const ViewData = observer(() => {
   return (
     <>
       <Flex alignItems="center">
+        <Button
+          mr="20px"
+          h="32px"
+          size="sm"
+          leftIcon={<AddIcon />}
+          {...defaultButtonStyle}
+          onClick={async (e) => {
+            const form = creatColumnDataForm(dbTable.currentColumns);
+            const formData = await hooks.getFormData({
+              title: `Insert data to '${dbTable.currentTable.tableName}'`,
+              size: 'md',
+              formList: [
+                {
+                  form
+                }
+              ]
+            });
+            try {
+              const keys = Object.keys(formData);
+              const values = Object.values(formData);
+              const errorMsg = await dbTable.createTableData(keys, values);
+              if (!errorMsg) {
+                const data = await dbTable.getCurrentTableData.call();
+                dbTable.table.set({
+                  dataSource: data
+                });
+              }
+            } catch (error) { }
+          }}
+        >
+          Insert
+        </Button>
         <label>
           <CSVReader
             label=""
@@ -207,7 +239,7 @@ const ViewData = observer(() => {
                 if (errorMsg) {
                   toast.error(errorMsg);
                 } else {
-                  const data = await dbTable.getCurrentTableData();
+                  const data = await dbTable.getCurrentTableData.call();
                   dbTable.table.set({
                     dataSource: data
                   });
@@ -231,43 +263,11 @@ const ViewData = observer(() => {
             inputName="csv-input"
             inputStyle={{ display: 'none' }}
           />
-          <Flex alignItems="center" px="20px" h="32px" borderRadius="4px" cursor="pointer" {...defaultButtonStyle}>
+          <Flex alignItems="center" px="10px" h="32px" borderRadius="6px" cursor="pointer" {...defaultButtonStyle}>
             <FiUpload />
-            <Box ml="10px" fontSize={"14px"}>Upload CSV</Box>
+            <Text ml="10px" fontSize="12px" fontWeight={600}>Upload CSV</Text>
           </Flex>
         </label>
-        <Button
-          ml="20px"
-          h="32px"
-          size="sm"
-          leftIcon={<AddIcon />}
-          {...defaultButtonStyle}
-          onClick={async (e) => {
-            const form = creatColumnDataForm(dbTable.currentColumns);
-            const formData = await hooks.getFormData({
-              title: `Insert data to '${dbTable.currentTable.tableName}'`,
-              size: 'md',
-              formList: [
-                {
-                  form
-                }
-              ]
-            });
-            try {
-              const keys = Object.keys(formData);
-              const values = Object.values(formData);
-              const errorMsg = await dbTable.createTableData(keys, values);
-              if (!errorMsg) {
-                const data = await dbTable.getCurrentTableData();
-                dbTable.table.set({
-                  dataSource: data
-                });
-              }
-            } catch (error) { }
-          }}
-        >
-          Insert
-        </Button>
         <Button
           ml="20px"
           h="32px"
@@ -275,7 +275,7 @@ const ViewData = observer(() => {
           leftIcon={<MdRefresh />}
           {...defaultOutlineButtonStyle}
           onClick={async (e) => {
-            dbTable.init();
+            dbTable.init.call();
           }}
         >
           Refresh
@@ -297,8 +297,6 @@ const QuerySQL = observer(() => {
     }, 800)
   );
 
-  const [queryResult, setQueryResult] = useState('');
-
   return (
     <Box bg="#000">
       <Box p="1" fontSize="sm" fontWeight={700} color="#fff">
@@ -321,15 +319,21 @@ const QuerySQL = observer(() => {
         />
         <Box
           pos="absolute"
-          bottom={4}
+          bottom={1}
           right={4}
           cursor="pointer"
-          onClick={async () => {
-            const result = await dbTable.querySQL();
-            setQueryResult(JSON.stringify(result, null, 2));
+          onClick={() => {
+            if (dbTable.querySQL.loading.value) {
+              return;
+            }
+            dbTable.querySQL.call();
           }}
         >
-          <Image p={1} h={6} w={6} borderRadius="4px" bg="#946FFF" _hover={{ background: 'gray.200' }} src="/images/icons/execute.svg" />
+          {
+            dbTable.querySQL.loading.value
+              ? <Spinner size="sm" color='#fff' />
+              : <Image p={1} h={6} w={6} borderRadius="4px" bg="#946FFF" _hover={{ background: 'gray.200' }} src="/images/icons/execute.svg" />
+          }
         </Box>
       </Box>
       <Box p="1" fontSize="sm" fontWeight={700} color="#fff">
@@ -345,7 +349,7 @@ const QuerySQL = observer(() => {
         height="calc(100vh - 480px)"
         theme="vs-dark"
         language="json"
-        value={queryResult}
+        value={dbTable.querySQL.value}
       />
     </Box>
   );
@@ -357,7 +361,7 @@ const DBTable = observer(() => {
   } = useStore();
 
   useEffect(() => {
-    dbTable.init();
+    dbTable.init.call();
   }, [dbTable.currentTable.tableSchema, dbTable.currentTable.tableName]);
 
   useEffect(() => {
diff --git a/src/components/IDE/DBTable/SideBar.tsx b/src/components/IDE/DBTable/SideBar.tsx
index 9eab3675..97867e63 100644
--- a/src/components/IDE/DBTable/SideBar.tsx
+++ b/src/components/IDE/DBTable/SideBar.tsx
@@ -1,7 +1,7 @@
 import React, { useEffect } from 'react';
 import { Flex, Box, Text, Tooltip, Button, useDisclosure, Collapse, Spinner } from '@chakra-ui/react';
 import { Icon } from '@chakra-ui/react';
-import { ChevronDownIcon, ChevronRightIcon, DeleteIcon, EditIcon, ViewIcon } from '@chakra-ui/icons';
+import { ChevronDownIcon, ChevronRightIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
 import { MdAddBox } from 'react-icons/md';
 import { observer } from 'mobx-react-lite';
 import { useStore } from '@/store/index';
@@ -19,14 +19,6 @@ export const DBTableSideBar = observer(() => {
     allTables.call();
   }, []);
 
-  if (allTables.loading.value) {
-    return (
-      <Flex w="100%" h="100%" justify="center">
-        <Spinner mt="100px" color="#946FFF" />
-      </Flex>
-    );
-  }
-
   if (!allTables.value) {
     return null;
   }
@@ -64,10 +56,11 @@ const TableNames = observer(({ tableSchema, tables }: { tableSchema: string; tab
         <Flex alignItems="center" overflowX="auto">
           <Icon as={collaspeState.isOpen ? ChevronDownIcon : ChevronRightIcon} boxSize={6} cursor="pointer" />
           <Box w="220px" fontSize="16x" fontWeight={700}>
-            {/* {tableSchema} */} Default
+            {tableSchema === 'public' ? "Default" : tableSchema}
           </Box>
         </Flex>
         <Flex alignItems="center">
+          {dbTable.allTables.loading.value && <Spinner size="sm" color="#946FFF" />}
           <Tooltip hasArrow label="Create a new table" placement="bottom">
             <Button
               p={0}
@@ -109,30 +102,20 @@ const TableNames = observer(({ tableSchema, tables }: { tableSchema: string; tab
               borderBottom="1px solid rgba(0, 0, 0, 0.06)"
               sx={getSelectedStyles(dbTable.currentTable.tableId === item.tableId)}
               cursor="pointer"
-              onClick={() => {
+              onClick={(e) => {
+                e.stopPropagation();
                 dbTable.setCurrentTable({
                   tableSchema,
                   tableId: item.tableId,
                   tableName: item.tableName
                 });
-                if (dbTable.mode === 'QUERY_SQL') {
-                  dbTable.setDefaultSQL();
-                }
+                dbTable.setMode('VIEW_DATA');
               }}
             >
               <Text
                 fontSize="14px"
                 fontWeight={600}
                 overflowX="auto"
-                onClick={(e) => {
-                  e.stopPropagation();
-                  dbTable.setCurrentTable({
-                    tableSchema,
-                    tableId: item.tableId,
-                    tableName: item.tableName
-                  });
-                  dbTable.setMode('VIEW_DATA');
-                }}
               >
                 {item.tableName}
               </Text>
@@ -172,22 +155,6 @@ const TableNames = observer(({ tableSchema, tables }: { tableSchema: string; tab
                     }}
                   />
                 </Tooltip>
-                <Tooltip hasArrow label="View Data" placement="bottom">
-                  <ViewIcon
-                    ml="12px"
-                    boxSize={4}
-                    cursor="pointer"
-                    onClick={(e) => {
-                      e.stopPropagation();
-                      dbTable.setCurrentTable({
-                        tableSchema,
-                        tableId: item.tableId,
-                        tableName: item.tableName
-                      });
-                      dbTable.setMode('VIEW_DATA');
-                    }}
-                  />
-                </Tooltip>
               </Flex>
             </Flex>
           );
diff --git a/src/components/IDE/DBTable/index.tsx b/src/components/IDE/DBTable/index.tsx
index e45abf67..1bb75260 100644
--- a/src/components/IDE/DBTable/index.tsx
+++ b/src/components/IDE/DBTable/index.tsx
@@ -17,14 +17,18 @@ const DeveloperDBTable = () => {
         <DBTable />
       </Box>
       {w3s.showContent === 'DB_TABLE' && (
-        <Box pos="absolute" right="0px" top="0px">
+        <Box pos="absolute" right={2} top="0px">
           <Tooltip label="Query SQL" placement="bottom">
             <Box
               position="relative"
               cursor="pointer"
               onClick={() => {
-                w3s.dbTable.setDefaultSQL();
-                w3s.dbTable.setMode('QUERY_SQL');
+                if (w3s.dbTable.mode === 'QUERY_SQL') {
+                  w3s.dbTable.setMode('VIEW_DATA');
+                } else {
+                  w3s.dbTable.setDefaultSQL();
+                  w3s.dbTable.setMode('QUERY_SQL');
+                }
               }}
             >
               <Image h={10} w={10} src="/images/icons/execute_sql.svg" />
diff --git a/src/store/lib/w3bstream/schema/dbTable.ts b/src/store/lib/w3bstream/schema/dbTable.ts
index 322994e3..feac8182 100644
--- a/src/store/lib/w3bstream/schema/dbTable.ts
+++ b/src/store/lib/w3bstream/schema/dbTable.ts
@@ -98,7 +98,12 @@ export type ExportTableType = {
 export default class DBTableModule {
   allTables = new PromiseState<() => Promise<any>, { schemaName: string; tables: TableType[] }[]>({
     loadingText: 'please waiting...',
-    defaultValue: [],
+    defaultValue: [
+      {
+        schemaName: 'public',
+        tables: []
+      }
+    ],
     function: async () => {
       return this.fetchTables({
         includeColumns: false
@@ -128,7 +133,7 @@ export default class DBTableModule {
         submitText: 'Submit',
         props: {
           style: {
-            marginTop:"100px"
+            marginTop: '100px'
           }
         }
       },
@@ -310,35 +315,29 @@ export default class DBTableModule {
     this.setSQL(sql);
   }
 
-  async querySQL() {
-    if (!this.sql) {
-      return {
-        errorMsg: 'SQL is empty'
-      };
-    }
-
-    try {
-      const curProjectId = globalThis.store.w3s.project.curProject?.f_project_id;
-      const { data, errorMsg } = await trpc.pg.query.mutate({
-        projectID: curProjectId,
-        sql: this.sql
-      });
-      if (errorMsg) {
-        toast.error(errorMsg);
-        return {
-          errorMsg
-        };
-      } else {
-        toast.success('This SQL was executed successfully');
-        return data;
+  querySQL = new PromiseState({
+    loadingText: 'please waiting...',
+    defaultValue: '',
+    function: async () => {
+      if (!this.sql) {
+        return 'SQL is empty';
+      }
+      try {
+        const curProjectId = globalThis.store.w3s.project.curProject?.f_project_id;
+        const { data, errorMsg } = await trpc.pg.query.mutate({
+          projectID: curProjectId,
+          sql: this.sql
+        });
+        if (errorMsg) {
+          return errorMsg;
+        } else {
+          return JSON.stringify(data, null, 2);
+        }
+      } catch (error) {
+        return error.message;
       }
-    } catch (error) {
-      toast.error(error.message);
-      return {
-        errorMsg: error.message
-      };
     }
-  }
+  });
 
   async fetchTables({ includeColumns }: { includeColumns: boolean }) {
     const curProjectId = globalThis.store.w3s.project.curProject?.f_project_id;
@@ -589,32 +588,35 @@ export default class DBTableModule {
     }
   }
 
-  async getCurrentTableData() {
-    const { tableSchema, tableName } = this.currentTable;
-    try {
-      const curProjectId = globalThis.store.w3s.project.curProject?.f_project_id;
-      const { data, errorMsg } = await trpc.pg.tableData.query({
-        projectID: curProjectId,
-        tableSchema,
-        tableName,
-        page: this.table.pagination.page,
-        pageSize: this.table.pagination.limit
-      });
-      if (errorMsg) {
-        toast.error(errorMsg);
+  getCurrentTableData = new PromiseState({
+    loadingText: 'please waiting...',
+    function: async () => {
+      const { tableSchema, tableName } = this.currentTable;
+      try {
+        const curProjectId = globalThis.store.w3s.project.curProject?.f_project_id;
+        const { data, errorMsg } = await trpc.pg.tableData.query({
+          projectID: curProjectId,
+          tableSchema,
+          tableName,
+          page: this.table.pagination.page,
+          pageSize: this.table.pagination.limit
+        });
+        if (errorMsg) {
+          toast.error(errorMsg);
+          return [];
+        } else {
+          return data;
+        }
+      } catch (error) {
+        if (error.message.includes('UNAUTHORIZED')) {
+          globalThis.store.w3s.config.logout();
+        } else {
+          toast.error(error.message);
+        }
         return [];
-      } else {
-        return data;
-      }
-    } catch (error) {
-      if (error.message.includes('UNAUTHORIZED')) {
-        globalThis.store.w3s.config.logout();
-      } else {
-        toast.error(error.message);
       }
-      return [];
     }
-  }
+  });
 
   async deleteTableData(name, value) {
     if (!name || !value) {
@@ -644,63 +646,65 @@ export default class DBTableModule {
     }
   }
 
-  async init() {
-    if (this.currentTable.tableSchema && this.currentTable.tableName) {
-      const [cols, count] = await Promise.all([this.getCurrentTableCols(), this.getCurrentTableDataCount()]);
-      const columns: Column[] = cols.map((item) => {
-        return {
-          key: item.name,
-          label: item.name
-        };
-      });
-
-      const idName = cols[0]?.name;
-      columns.push({
-        key: 'action',
-        label: 'Action',
-        actions: (item) => {
-          return [
-            {
-              props: {
-                size: 'xs',
-                ...defaultOutlineButtonStyle,
-                onClick: async () => {
-                  globalThis.store.base.confirm.show({
-                    title: 'Warning',
-                    description: 'Are you sure you want to delete it?',
-                    onOk: async () => {
-                      try {
-                        await this.deleteTableData(idName, item[idName]);
-                        const data = await this.getCurrentTableData();
-                        this.table.set({
-                          dataSource: data
-                        });
-                      } catch (error) {}
-                    }
-                  });
-                }
-              },
-              text: 'Delete'
-            }
-          ];
-        }
-      });
+  init = new PromiseState({
+    loadingText: 'please waiting...',
+    function: async () => {
+      if (this.currentTable.tableSchema && this.currentTable.tableName) {
+        const [cols, count] = await Promise.all([this.getCurrentTableCols(), this.getCurrentTableDataCount()]);
+        const columns: Column[] = cols.map((item) => {
+          return {
+            key: item.name,
+            label: item.name
+          };
+        });
+        const idName = cols[0]?.name;
+        columns.push({
+          key: 'action',
+          label: 'Action',
+          actions: (item) => {
+            return [
+              {
+                props: {
+                  size: 'xs',
+                  ...defaultOutlineButtonStyle,
+                  onClick: async () => {
+                    globalThis.store.base.confirm.show({
+                      title: 'Warning',
+                      description: 'Are you sure you want to delete it?',
+                      onOk: async () => {
+                        try {
+                          await this.deleteTableData(idName, item[idName]);
+                          const data = await this.getCurrentTableData.call();
+                          this.table.set({
+                            dataSource: data
+                          });
+                        } catch (error) {}
+                      }
+                    });
+                  }
+                },
+                text: 'Delete'
+              }
+            ];
+          }
+        });
 
-      this.table.set({
-        columns
-      });
+        this.table.set({
+          columns
+        });
 
-      this.table.pagination.setData({
-        page: 1,
-        total: Number(count)
-      });
+        this.table.pagination.setData({
+          page: 1,
+          total: Number(count)
+        });
 
-      this.setCurrentColumns(cols);
+        this.setCurrentColumns(cols);
+      }
     }
-  }
+  });
 
   async onPageChange() {
-    const data = await this.getCurrentTableData();
+    const data = await this.getCurrentTableData.call();
     this.table.set({
       dataSource: data
     });
@@ -739,18 +743,18 @@ export default class DBTableModule {
 
   async importTables({ projectID, schemas }: { projectID: string; schemas: ExportTableType[] }) {
     if (!schemas || !Array.isArray(schemas)) {
-      toast.error('No data provided')
+      toast.error('No data provided');
       return;
     }
     for (const schema of schemas) {
       const tables = schema?.tables;
       if (!tables || !Array.isArray(tables)) {
-        toast.error('No data provided')
+        toast.error('No data provided');
         return;
       }
       for (const t of tables) {
         if (!t.tableName || !t.tableSchema) {
-          toast.error('No data provided')
+          toast.error('No data provided');
           return;
         }
         try {
diff --git a/src/store/standard/PromiseState.ts b/src/store/standard/PromiseState.ts
index 1e207890..9bbe0932 100644
--- a/src/store/standard/PromiseState.ts
+++ b/src/store/standard/PromiseState.ts
@@ -2,7 +2,6 @@ import { makeAutoObservable } from 'mobx';
 import { BooleanState } from './base';
 import toast from 'react-hot-toast';
 
-
 export class PromiseState<T extends (...args: any[]) => Promise<any>, U = ReturnType<T>> {
   loading = new BooleanState();
   value?: Awaited<U> = null;
@@ -12,12 +11,15 @@ export class PromiseState<T extends (...args: any[]) => Promise<any>, U = Return
   autoAlert = true;
   context: any = undefined;
 
-  loadingText = null
-  loadingId = null
+  loadingText = null;
+  loadingId = null;
 
   currentIndex = 0;
   get current() {
-    return this.value[this.currentIndex];
+    if (Array.isArray(this.value)) {
+      return this.value[this.currentIndex];
+    }
+    return null;
   }
 
   constructor(args: Partial<PromiseState<T, U>> = {}) {
@@ -36,7 +38,7 @@ export class PromiseState<T extends (...args: any[]) => Promise<any>, U = Return
     try {
       this.loading.setValue(true);
       if (this.loadingText) {
-        this.loadingId = toast.loading(this.loadingText)
+        this.loadingId = toast.loading(this.loadingText);
       }
       const res = await this.function.apply(this.context, args);
       this.value = res;
@@ -54,7 +56,7 @@ export class PromiseState<T extends (...args: any[]) => Promise<any>, U = Return
         throw error;
       }
     } finally {
-      this.loadingId && toast.dismiss(this.loadingId)
+      this.loadingId && toast.dismiss(this.loadingId);
       this.loading.setValue(false);
     }
   }

From 50fafff2423ea5fae34f339bb58a2ca94987af33 Mon Sep 17 00:00:00 2001
From: osdodo <osdodo@qq.com>
Date: Fri, 2 Jun 2023 13:26:15 +0800
Subject: [PATCH 2/2] test script support output logs

---
 .../EditorBottomPanels/ConsolePanel.tsx       | 31 ++++++--
 .../IDE/Editor/EditorBottomPanels/DBpanel.tsx | 76 +------------------
 .../IDE/Editor/EditorFunctions/demo.ts        | 15 ++--
 .../IDE/Editor/MonacEditor/index.tsx          |  2 +-
 src/constants/initWASMExamples.ts             |  2 +
 5 files changed, 36 insertions(+), 90 deletions(-)

diff --git a/src/components/IDE/Editor/EditorBottomPanels/ConsolePanel.tsx b/src/components/IDE/Editor/EditorBottomPanels/ConsolePanel.tsx
index 0c2df335..4422453d 100644
--- a/src/components/IDE/Editor/EditorBottomPanels/ConsolePanel.tsx
+++ b/src/components/IDE/Editor/EditorBottomPanels/ConsolePanel.tsx
@@ -1,15 +1,26 @@
 import dayjs from '@/lib/dayjs';
+import { StdIOType } from '@/server/wasmvm';
 import { useStore } from '@/store/index';
 import { Box, Flex } from '@chakra-ui/react';
 import { observer } from 'mobx-react-lite';
 import { useEffect, useRef } from 'react';
-import { VscClearAll, VscDebugStart } from 'react-icons/vsc';
+import { VscClearAll } from 'react-icons/vsc';
+
+const stringify = (val: Partial<StdIOType>) => {
+  try {
+    return JSON.stringify(val);
+  } catch (error) {
+    return JSON.stringify({
+      '@lv': val['@lv'],
+      '@ts': val['@ts'],
+      msg: error.message
+    });
+  }
+}
 
 export const ConsolePanel = observer(() => {
   const {
-    w3s,
     w3s: {
-      projectManager: { curFilesListSchema },
       lab
     }
   } = useStore();
@@ -59,12 +70,18 @@ export const ConsolePanel = observer(() => {
         {lab.stdout?.map((i) => {
           return (
             <Flex color={i?.['@lv'] == 'error' ? 'red' : ''}>
-              <Flex maxW="200px" mr={2} whiteSpace="nowrap">
-                [<Box color="#d892ff">{i.prefix} </Box>
+              <Flex mr={2} whiteSpace="nowrap">
+                [<Box color="#d892ff">{i.prefix}</Box>
                 <Box color="#ffd300">{dayjs(i?.['@ts']).format('hh:mm:ss')}</Box>]
               </Flex>
-              <Flex w="90%" overflowWrap={'anywhere'}>
-                {JSON.stringify(i)}
+              <Flex>
+                {stringify(
+                  {
+                    '@lv': i?.['@lv'],
+                    '@ts': i?.['@ts'],
+                    msg: i?.msg
+                  }
+                )}
               </Flex>
             </Flex>
           );
diff --git a/src/components/IDE/Editor/EditorBottomPanels/DBpanel.tsx b/src/components/IDE/Editor/EditorBottomPanels/DBpanel.tsx
index bc57115e..157cbf0d 100644
--- a/src/components/IDE/Editor/EditorBottomPanels/DBpanel.tsx
+++ b/src/components/IDE/Editor/EditorBottomPanels/DBpanel.tsx
@@ -1,22 +1,19 @@
 import JSONTable from '@/components/JSONTable';
-import dayjs from '@/lib/dayjs';
 import { eventBus } from '@/lib/event';
 import { TableJSONSchema } from '@/server/wasmvm/sqldb';
 import { useStore } from '@/store/index';
 import { JSONSchemaTableState } from '@/store/standard/JSONSchemaState';
 import { Box, Flex, Input, Tabs, TabList, TabPanels, Tab, TabPanel } from '@chakra-ui/react';
 import { observer, useLocalObservable } from 'mobx-react-lite';
-import { useEffect, useRef } from 'react';
+import { useEffect } from 'react';
 import toast from 'react-hot-toast';
-import { VscClearAll, VscDebugStart } from 'react-icons/vsc';
+import { VscDebugStart } from 'react-icons/vsc';
 
 export const DBpanel = observer(() => {
   const {
     god: { sqlDB },
-    w3s,
     w3s: {
       projectManager: { curFilesListSchema },
-      lab
     }
   } = useStore();
   const store = useLocalObservable(() => ({
@@ -123,72 +120,3 @@ export const DBpanel = observer(() => {
     </Box>
   );
 });
-
-export const ConsolePanel = observer(() => {
-  const {
-    w3s: {
-      lab
-    }
-  } = useStore();
-  const terminalRef = useRef(null);
-
-  useEffect(() => {
-    terminalRef.current.scrollTop = terminalRef.current.scrollHeight * 10000;
-  }, [lab.stdout]);
-
-  return (
-    <>
-      <Flex borderTop={'2px solid #090909'} bg="#1e1e1e" color="white" pt={1}>
-        <VscClearAll
-          onClick={() => {
-            lab.stdout = [];
-            lab.stderr = [];
-          }}
-          cursor={'pointer'}
-          style={{ marginLeft: 'auto', marginRight: '20px' }}
-        />
-      </Flex>
-      <Box
-        css={{
-          '&::-webkit-scrollbar': {
-            width: '8px'
-          },
-          '&::-webkit-scrollbar-track': {
-            width: '8px'
-          },
-          '&::-webkit-scrollbar-thumb': {
-            background: '#999999'
-            // borderRadius: '24px'
-          }
-        }}
-        ref={terminalRef}
-        id="terminal"
-        fontFamily="monospace"
-        w="100%"
-        h="calc(100vh - 580px)"
-        p="10px"
-        bg="#1e1e1e"
-        color="white"
-        whiteSpace="pre-line"
-        overflowY="auto"
-        position="relative"
-      >
-        {lab.stdout?.map((i) => {
-          return (
-            <Flex color={i?.['@lv'] == 'error' ? 'red' : ''}>
-              <Flex mr={2} whiteSpace="nowrap">
-                [<Box color="#d892ff">{i.prefix}</Box>
-                <Box color="#ffd300">{dayjs(i?.['@ts']).format('hh:mm:ss')}</Box>]
-              </Flex>
-              {JSON.stringify({
-                '@lv': i?.['@lv'],
-                '@ts': i?.['@ts'],
-                msg: i?.msg
-              })}
-            </Flex>
-          );
-        })}
-      </Box>
-    </>
-  );
-});
diff --git a/src/components/IDE/Editor/EditorFunctions/demo.ts b/src/components/IDE/Editor/EditorFunctions/demo.ts
index 9bb1b3d4..3db0877f 100644
--- a/src/components/IDE/Editor/EditorFunctions/demo.ts
+++ b/src/components/IDE/Editor/EditorFunctions/demo.ts
@@ -216,21 +216,20 @@ class W3bstream {
   }
 }
 
+const Log = (msg: string) => {
+  const lab = globalThis.store.w3s.lab;
+  lab.stdout.push({ '@lv': 'info', msg, '@ts': Date.now(), prefix: '' });
+};
+
 export const debugDemo = new PromiseState<() => Promise<any>, any>({
   function: async () => {
     const lab = globalThis.store.w3s.lab;
     const code = globalThis.store.w3s.projectManager.curFilesListSchema.curActiveFile.data.code;
-
-    let errMsg = '';
-    let msg = '';
     try {
-      const res = await new Function('Wallet', 'BlockChain', 'W3bstream', code)(Wallet, BlockChain, W3bstream);
+      const res = await new Function('Wallet', 'BlockChain', 'W3bstream', 'Log', code)(Wallet, BlockChain, W3bstream, Log);
       console.log('[Demo Return Value]:', res);
     } catch (error) {
-      errMsg = error.message;
+      lab.stdout.push({ '@lv': 'error', msg: error.message, '@ts': Date.now(), prefix: '' });
     }
-
-    const stdio: StdIOType = errMsg ? { '@lv': 'error', msg: errMsg, '@ts': Date.now(), prefix: '' } : { '@lv': 'info', msg, '@ts': Date.now(), prefix: '' };
-    lab.stdout.push(stdio);
   }
 });
diff --git a/src/components/IDE/Editor/MonacEditor/index.tsx b/src/components/IDE/Editor/MonacEditor/index.tsx
index 6ff8a451..ae4b55ef 100644
--- a/src/components/IDE/Editor/MonacEditor/index.tsx
+++ b/src/components/IDE/Editor/MonacEditor/index.tsx
@@ -44,7 +44,7 @@ export const MoEditor = observer((props: any) => {
         onMount={async (editor, monaco) => {
           monaco.languages.typescript.typescriptDefaults.addExtraLib(
             `
-      declare const Log: (message:string) => void;
+      declare const Log: (message: string | { [x: string]: any }) => void;
       declare const SetDB: (key: string, value: number) => void;
       declare const GetDB: (key: string) => string;
       declare const SendTx: (chainId: number, to:string, value:string ,data:string) => string | null;
diff --git a/src/constants/initWASMExamples.ts b/src/constants/initWASMExamples.ts
index b4909409..71e6a322 100644
--- a/src/constants/initWASMExamples.ts
+++ b/src/constants/initWASMExamples.ts
@@ -363,6 +363,8 @@ export const demoExample: FilesItemType = {
 
   const data = await w3bstream.getData('SELECT * FROM demo ORDER BY id DESC LIMIT 1')
 
+  Log(data)
+
   return {
     contract,
     data,