2025-01-09 12:32:24 +00:00
|
|
|
import { OmnibusRegistrator } from "@hypersphere/omnibus";
|
2025-01-10 11:03:43 +00:00
|
|
|
import { App, MarkdownPostProcessorContext, MarkdownRenderChild, TFile } from "obsidian";
|
2025-01-09 12:32:24 +00:00
|
|
|
import { SqlSealDatabase } from "src/database/database";
|
|
|
|
|
import { Sync } from "src/datamodel/sync";
|
|
|
|
|
import { parseLanguage, Table } from "src/grammar/newParser";
|
|
|
|
|
import { RendererRegistry, RenderReturn } from "src/renderer/rendererRegistry";
|
2025-01-15 17:48:33 +00:00
|
|
|
import { transformQuery } from "src/sql/sqlTransformer";
|
2025-01-15 20:34:16 +00:00
|
|
|
import { registerObservers } from "src/utils/registerObservers";
|
2025-01-09 12:32:24 +00:00
|
|
|
import { displayError, displayNotice } from "src/utils/ui";
|
2025-01-08 19:58:14 +00:00
|
|
|
|
2025-01-09 12:32:24 +00:00
|
|
|
export class CodeblockProcessor extends MarkdownRenderChild {
|
2025-01-08 19:58:14 +00:00
|
|
|
|
|
|
|
|
registrator: OmnibusRegistrator
|
|
|
|
|
renderer: RenderReturn
|
2024-09-02 18:40:48 +00:00
|
|
|
|
2024-11-02 15:23:44 +00:00
|
|
|
constructor(
|
2025-01-08 19:58:14 +00:00
|
|
|
private el: HTMLElement,
|
|
|
|
|
private source: string,
|
|
|
|
|
private ctx: MarkdownPostProcessorContext,
|
|
|
|
|
private rendererRegistry: RendererRegistry,
|
|
|
|
|
private db: SqlSealDatabase,
|
|
|
|
|
private app: App,
|
|
|
|
|
private sync: Sync) {
|
|
|
|
|
super(el)
|
|
|
|
|
this.registrator = this.sync.getRegistrator()
|
2024-09-02 18:40:48 +00:00
|
|
|
}
|
2024-09-01 13:01:54 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
query: string;
|
2024-11-02 15:23:44 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
async onload() {
|
|
|
|
|
try {
|
|
|
|
|
const results = parseLanguage(this.source)
|
|
|
|
|
if (results.tables) {
|
|
|
|
|
await this.registerTables(results.tables)
|
|
|
|
|
if (!results.queryPart) {
|
|
|
|
|
displayNotice(this.el, `Creating tables: ${results.tables.map(t => t.tableName).join(', ')}`)
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-02 15:23:44 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
this.renderer = this.rendererRegistry.prepareRender(results.intermediateContent)(this.el)
|
|
|
|
|
|
|
|
|
|
// FIXME: probably should save the one before transform and perform transform every time we execute it.
|
|
|
|
|
this.query = results.queryPart
|
|
|
|
|
await this.render()
|
|
|
|
|
} catch (e) {
|
|
|
|
|
displayError(this.el, e.toString())
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-02 15:23:44 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
onunload() {
|
|
|
|
|
this.registrator.offAll()
|
2024-11-02 15:23:44 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
async render() {
|
|
|
|
|
try {
|
2024-09-02 18:40:48 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
const registeredTablesForContext = await this.sync.getTablesMappingForContext(this.ctx.sourcePath)
|
2024-09-02 18:40:48 +00:00
|
|
|
|
2025-01-15 17:48:33 +00:00
|
|
|
const res = transformQuery(this.query, registeredTablesForContext)
|
|
|
|
|
const transformedQuery = res.sql
|
2024-11-02 15:23:44 +00:00
|
|
|
|
2025-01-15 20:34:16 +00:00
|
|
|
registerObservers({
|
|
|
|
|
bus: this.registrator,
|
|
|
|
|
callback: () => this.render(),
|
|
|
|
|
fileName: this.ctx.sourcePath,
|
|
|
|
|
tables: res.mappedTables
|
2025-01-08 19:58:14 +00:00
|
|
|
})
|
2024-11-07 18:43:15 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
|
|
|
|
|
const file = this.app.vault.getFileByPath(this.ctx.sourcePath)
|
|
|
|
|
if (!file) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const fileCache = this.app.metadataCache.getFileCache(file)
|
2025-01-15 17:48:33 +00:00
|
|
|
const { data, columns } = await this.db.select(transformedQuery, fileCache?.frontmatter ?? {})
|
2025-01-08 19:58:14 +00:00
|
|
|
this.renderer.render({ data, columns })
|
|
|
|
|
} catch (e) {
|
|
|
|
|
this.renderer.error(e.toString())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async registerTables(tables: Table[]) {
|
|
|
|
|
await Promise.all(tables.map((table) => {
|
2025-01-10 11:03:43 +00:00
|
|
|
let path: TFile | null = null
|
|
|
|
|
let extras = {}
|
|
|
|
|
if (table.type !== 'table') {
|
|
|
|
|
path = this.app.metadataCache.getFirstLinkpathDest(table.fileName, this.ctx.sourcePath)
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
path = this.app.vault.getFileByPath(this.ctx.sourcePath)
|
|
|
|
|
extras = {
|
|
|
|
|
tableNo: table.fileName // FIXME: this should be returned under better name.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
if (!path) {
|
|
|
|
|
throw new Error(`File does not exist: ${table.fileName} (for ${table.tableName}).`)
|
2024-09-02 18:40:48 +00:00
|
|
|
}
|
2025-01-10 11:03:43 +00:00
|
|
|
|
2025-01-08 19:58:14 +00:00
|
|
|
return this.sync.registerTable({
|
|
|
|
|
aliasName: table.tableName,
|
2025-01-10 11:03:43 +00:00
|
|
|
type: table.type,
|
2025-01-08 19:58:14 +00:00
|
|
|
fileName: path.path,
|
2025-01-10 11:03:43 +00:00
|
|
|
sourceFile: this.ctx.sourcePath,
|
|
|
|
|
extras
|
2025-01-08 19:58:14 +00:00
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
}
|
2024-09-01 13:01:54 +00:00
|
|
|
}
|