feat: adding advanced mode

This commit is contained in:
Kacper Kula 2025-03-15 11:06:44 +00:00
parent 732577fae5
commit 37f746b72c
6 changed files with 870 additions and 777 deletions

33
docs/advanced-mode.md Normal file
View file

@ -0,0 +1,33 @@
# Advanced Mode
You can turn on Advanced mode which will enable you to write pure JavaScript. You have access to your query result and helper functions inside it so you can use it to transform your data, perform additional logic, etc.
In advanced mode you need to return manually the object that will be used as a chart configuration in the end.
## Example
More advanced examples to be added later.
```sqlseal
ADVANCED MODE
-- now you can use all JavaScript syntax to your heart content
CHART
const values = (new Array(5)).map((_, i) => i)
return {
tooltip: {},
legend: {
data: ['sales']
},
xAxis: {
data: ['Shirts', 'Cardigans', 'Chiffons', 'Pants', 'Heels', 'Socks']
},
yAxis: {},
series: [
{
name: 'sales',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
}
SELECT * FROM files
```

View file

@ -31,29 +31,29 @@
"@types/acorn": "^6.0.4",
"@types/estree": "^1.0.6",
"@types/jest": "^29.5.14",
"@types/node": "^22.12.0",
"@typescript-eslint/eslint-plugin": "^8.22.0",
"@typescript-eslint/parser": "^8.22.0",
"builtin-modules": "^4.0.0",
"esbuild": "^0.24.2",
"@types/node": "^22.13.10",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"builtin-modules": "^5.0.0",
"esbuild": "^0.25.1",
"jest": "^29.7.0",
"obsidian": "^1.7.2",
"ts-jest": "^29.2.5",
"obsidian": "^1.8.7",
"ts-jest": "^29.2.6",
"tslib": "^2.8.1",
"typescript": "^5.7.3"
"typescript": "^5.8.2"
},
"dependencies": {
"@hypersphere/sqlseal": "^0.21.0",
"@hypersphere/sqlseal": "^0.28.0",
"@types/leaflet": "^1.9.16",
"@types/lodash": "^4.17.15",
"@types/lodash": "^4.17.16",
"@vanakat/plugin-api": "^0.2.1",
"acorn": "^8.14.0",
"acorn": "^8.14.1",
"echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"json5": "^2.2.3",
"lodash": "^4.17.21",
"vitepress": "^1.6.3",
"vue": "^3.5.13",
"zod": "^3.24.1"
"zod": "^3.24.2"
}
}

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,8 @@ import { parseCode } from "./utils/configParser";
import { prepareDataVariables } from "./utils/prepareDataVariables";
import * as echarts from 'echarts';
import type { RendererConfig } from "@hypersphere/sqlseal";
import { ViewDefinition } from "@hypersphere/sqlseal/dist/src/grammar/parser";
import { parseCodeAdvanced } from "./utils/advancedParser";
interface Config {
config: string
@ -13,21 +15,46 @@ export class ChartRenderer implements RendererConfig {
constructor(private readonly app: App) {
}
get viewDefinition(): ViewDefinition {
return {
argument: 'javascriptTemplate',
name: 'chart',
singleLine: false
}
}
get rendererKey() {
return 'chart'
}
validateConfig(config: string): Config {
return { config }
return { config: config.trim() }
}
render(config: Config, el: HTMLElement) {
let isRendered: boolean = false
let chart: echarts.ECharts | null = null
return {
render: ({ columns, data }: { columns: string[], data: Record<string, unknown>[]}) => {
render: ({ columns, data, flags }: { columns: string[], data: Record<string, unknown>[], flags: Record<string, boolean> }) => {
const isAdvancedMode = !!(flags?.isAdvancedMode)
if (config.config[0] !== '{' && !isAdvancedMode) {
throw new Error('To process JavaScript, set ADVANCED MODE flag')
}
const { functions, variables } = prepareDataVariables({ columns, data })
const parsedConfig = parseCode(config.config, functions, variables)
let parsedConfig: Object = {}
if (isAdvancedMode) {
try {
parsedConfig = parseCodeAdvanced({ functions, variables }, config.config)
} catch (e) {
console.error(e)
throw e
}
} else {
parsedConfig = parseCode(config.config, functions, variables) as Object
}
if (!parsedConfig || typeof parsedConfig !== 'object') {
throw new Error('Issue with parsing config')
}

View file

@ -13,5 +13,9 @@ export default class SQLSealCharts extends Plugin {
const api = pluginApi('sqlseal') as SQLSealRegisterApi
const registar = api.registerForPlugin(this)
registar.registerView('sqlseal-charts', new ChartRenderer(this.app))
if (api.apiVersion >= 2) {
registar.registerFlag({ key: 'isAdvancedMode', name: 'ADVANCED MODE' })
}
}
}

View file

@ -0,0 +1,22 @@
import { uniqBy } from "lodash"
type Params = {
functions: Record<string, any>,
variables: Record<string, any>
}
export const parseCodeAdvanced = ({ functions, variables }: Params, code: string) => {
const { keys, values } = uniqBy([
...Object.entries(functions),
...Object.entries({
data: variables.data,
columns: variables.columns
})
], 0).reduce(({ keys, values}, [key, value]) => ({
keys: [...keys, key],
values: [...values, value]
}), { keys: [], values: []})
const fn = new Function(...keys, code)
return fn(...values)
}