import { Database, Statement } from "https://deno.land/x/sqlite3@0.9.1/mod.ts"; import * as path from 'https://deno.land/std@0.102.0/path/mod.ts'; import { TokenTags } from "../language/tags.ts"; import "../util/string.ts"; export interface DBDictInfo { id: number; name: string; language: string; priority: number; }; export interface FindResult { id: number; expression: string; reading: string; tags: TokenTags; sort: number; depth: number; original: string; match: { kanji: boolean; reading: boolean; }; } interface DBFindResult { id: number; expression: string; reading: string; tags: string; rules: string; depth: number; original: string; deinflected: string; root_overlay: number; user_overlay: number; } /** * @summary dictionary database connection, handles deconjugation and lookup in SQL * * @example * const db = new DB(); * await db.prepare(); * const results = db.findTerm("なった"); */ export default class DB { private connection: Database; public ready: Promise; private here = path.dirname(path.fromFileUrl(import.meta.url)); private paths = { db: { dict: path.resolve(this.here, 'dict.db'), user: path.resolve(this.here, 'user.db'), }, query: { find: path.resolve(this.here, 'find.sql'), }, } as const; private statement: { attach: Statement; queryTerm: Statement; }; constructor() { this.connection = new Database(":memory:", { create: false }); this.statement = { attach: this.connection.prepare("attach database ? as ?"), queryTerm: this.connection.prepare(""), }; this.attach(this.paths.db.dict, 'dict'); this.attach(this.paths.db.user, 'user'); this.ready = new Promise(async resolve => { const statement = await Deno.readTextFile(this.paths.query.find); this.statement.queryTerm = this.connection.prepare(statement); resolve(); }); } private attach(dbPath: string, alias?: string) { this.statement.attach.run(dbPath, alias); } async findTerm(term: string): Promise { await this.ready; var results = this.statement.queryTerm.all({ term }) as unknown as DBFindResult[]; var terms: FindResult[] = results?.map(term => { if (term.rules == null) term.rules = ""; return { id: term.id, expression: term.expression, reading: term.reading, tags: (term.tags + ' ' + term.rules).parseTags(), sort: term.user_overlay ?? term.root_overlay ?? 100, depth: term.depth, original: term.original, match: { kanji: term.expression == term.deinflected, reading: term.reading == term.deinflected, }, }; }); return terms; } };