getting words
This commit is contained in:
1 parent
154c55a7bb
commit
b76d115d7e
5 files changed
+124
-39
No files matched your search
@@ -7,6 +7,8 @@
|
|||||||
// т.е. количество дней с 1970-01-01, без времени;
|
// т.е. количество дней с 1970-01-01, без времени;
|
||||||
// - states.fsrs_memory: сырое INTEGER-значение FSRS (не дата, не трогаем).
|
// - states.fsrs_memory: сырое INTEGER-значение FSRS (не дата, не трогаем).
|
||||||
|
|
||||||
|
import { query } from "./sqlite-api";
|
||||||
|
|
||||||
export interface CustomField {
|
export interface CustomField {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -40,6 +42,18 @@ export interface Word {
|
|||||||
group_id: number;
|
group_id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function wordList() {
|
||||||
|
let rows = await query("SELECT id, key, value, tags, more, group_id FROM words");
|
||||||
|
return rows.map((row: any) => ({
|
||||||
|
id: row.id,
|
||||||
|
key: row.key,
|
||||||
|
value: row.value,
|
||||||
|
tags: row.tags,
|
||||||
|
more: row.more,
|
||||||
|
group_id: row.group_id,
|
||||||
|
})) as Word[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface HistoryEntry {
|
export interface HistoryEntry {
|
||||||
id: number;
|
id: number;
|
||||||
deck_id: number;
|
deck_id: number;
|
||||||
|
|||||||
+24
-19
@@ -4,47 +4,52 @@ import { DB_FILENAME } from './opfs';
|
|||||||
let db: any | null = null;
|
let db: any | null = null;
|
||||||
|
|
||||||
self.onmessage = async (e) => {
|
self.onmessage = async (e) => {
|
||||||
|
const { type, id, sql, params } = e.data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(e.data.type)
|
console.log(e.data.type)
|
||||||
switch (e.data.type) {
|
switch (type) {
|
||||||
case 'start': {
|
case 'start': {
|
||||||
try {
|
if (db != null) {
|
||||||
const sqlite3 = await sqlite3InitModule({
|
self.postMessage({ type: 'success', id, data: null });
|
||||||
print: console.log,
|
return;
|
||||||
printErr: console.error, // Сюда будут падать детали ошибок VFS
|
|
||||||
});
|
|
||||||
const filename = '/' + DB_FILENAME;
|
|
||||||
db = new sqlite3.oo1.OpfsDb(filename, 'rwt');
|
|
||||||
|
|
||||||
db.exec('PRAGMA foreign_keys = ON;');
|
|
||||||
self.postMessage({ type: 'success' });
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(err);
|
|
||||||
self.postMessage({ type: 'error', message: err.message });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sqlite3 = await sqlite3InitModule({
|
||||||
|
print: console.log,
|
||||||
|
printErr: console.error, // Сюда будут падать детали ошибок VFS
|
||||||
|
});
|
||||||
|
const filename = '/' + DB_FILENAME;
|
||||||
|
db = new sqlite3.oo1.OpfsDb(filename, 'rwt');
|
||||||
|
|
||||||
|
db.exec('PRAGMA foreign_keys = ON;');
|
||||||
|
|
||||||
|
self.postMessage({ type: 'success', id, data: null });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'query': {
|
case 'query': {
|
||||||
if (db === null) throw new Error('БД не инициализирована');
|
if (db === null) throw new Error('БД не инициализирована');
|
||||||
const result = db.selectObjects(e.data.sql, e.data.params);
|
const result = db.selectObjects(sql, params);
|
||||||
self.postMessage({ type: 'success', result });
|
self.postMessage({ type: 'success', id, data: result });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'command': {
|
case 'command': {
|
||||||
if (db === null) throw new Error('БД не инициализирована');
|
if (db === null) throw new Error('БД не инициализирована');
|
||||||
db.exec(e.data.sql, e.data.params);
|
db.exec(sql, params);
|
||||||
self.postMessage({ type: 'success' });
|
self.postMessage({ type: 'success', id, data: null });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'close': {
|
case 'close': {
|
||||||
if (db === null) throw new Error('БД не инициализирована');
|
if (db === null) throw new Error('БД не инициализирована');
|
||||||
db.close();
|
db.close();
|
||||||
|
db = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
self.postMessage({ type: 'error', message: err.message });
|
self.postMessage({ type: 'error', message: err.message , id});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Главная страница: статус локальной базы + быстрый переход к синхронизации.
|
// Главная страница: статус локальной базы + быстрый переход к синхронизации.
|
||||||
// Никакой БД-логики кроме проверки наличия файла в OPFS.
|
// Никакой БД-логики кроме проверки наличия файла в OPFS.
|
||||||
|
|
||||||
|
import { wordList } from './db-types.ts';
|
||||||
import { worker } from './main.ts';
|
import { worker } from './main.ts';
|
||||||
import { hasDatabaseFile, readDatabaseFile } from './opfs.ts';
|
import { hasDatabaseFile, readDatabaseFile } from './opfs.ts';
|
||||||
import { looksLikeSQLite } from './zstd.ts';
|
import { looksLikeSQLite } from './zstd.ts';
|
||||||
@@ -48,6 +49,10 @@ export function renderHomePage(root: HTMLElement, nav: HomeNav): void {
|
|||||||
? `Локальная база на месте: ${(raw.length / 1024).toFixed(1)} КБ, сигнатура SQLite OK.`
|
? `Локальная база на месте: ${(raw.length / 1024).toFixed(1)} КБ, сигнатура SQLite OK.`
|
||||||
: 'Файл в OPFS есть, но это не похоже на SQLite — перекачай сохранение.';
|
: 'Файл в OPFS есть, но это не похоже на SQLite — перекачай сохранение.';
|
||||||
actions.hidden = !ok;
|
actions.hidden = !ok;
|
||||||
|
if (ok) {
|
||||||
|
let list = await wordList();
|
||||||
|
console.log(list);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
statusEl.textContent = `Не удалось прочитать базу: ${err instanceof Error ? err.message : String(err)}`;
|
statusEl.textContent = `Не удалось прочитать базу: ${err instanceof Error ? err.message : String(err)}`;
|
||||||
actions.hidden = true;
|
actions.hidden = true;
|
||||||
|
|||||||
+4
-20
@@ -1,31 +1,12 @@
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
import { renderHomePage } from './home-page.ts';
|
import { renderHomePage } from './home-page.ts';
|
||||||
import { renderSyncPage } from './sync-page.ts';
|
import { renderSyncPage } from './sync-page.ts';
|
||||||
|
import { initWorker } from './sqlite-api.ts';
|
||||||
|
|
||||||
export const worker = new Worker(new URL('./db-worker.ts', import.meta.url), {
|
export const worker = new Worker(new URL('./db-worker.ts', import.meta.url), {
|
||||||
type: 'module',
|
type: 'module',
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.onerror = (ee) => {
|
|
||||||
console.log(ee)
|
|
||||||
};
|
|
||||||
|
|
||||||
worker.onmessageerror = (ee) => {
|
|
||||||
console.log(ee)
|
|
||||||
};
|
|
||||||
worker.onmessage = (e) => {
|
|
||||||
if (e.data.type === 'success') {
|
|
||||||
const app = document.getElementById('app');
|
|
||||||
if (app) {
|
|
||||||
console.log(e.data.rows)
|
|
||||||
}
|
|
||||||
} else if (e.data.type === 'error') {
|
|
||||||
console.error(e.data.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
worker.postMessage({ type: 'start' });
|
|
||||||
|
|
||||||
// Каркас приложения: топ-бар + бургер-меню + две страницы (Главная / Синхронизация).
|
// Каркас приложения: топ-бар + бургер-меню + две страницы (Главная / Синхронизация).
|
||||||
|
|
||||||
type Page = 'home' | 'sync';
|
type Page = 'home' | 'sync';
|
||||||
@@ -94,7 +75,10 @@ drawer.querySelectorAll<HTMLButtonElement>('.drawer-btn').forEach((btn) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Старт: главная страница, меню закрыто
|
// Старт: главная страница, меню закрыто
|
||||||
|
await initWorker();
|
||||||
setDrawer(false);
|
setDrawer(false);
|
||||||
renderPage('home');
|
renderPage('home');
|
||||||
console.log('[JapLearn] crossOriginIsolated =', window.crossOriginIsolated);
|
console.log('[JapLearn] crossOriginIsolated =', window.crossOriginIsolated);
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { worker } from "./main";
|
||||||
|
|
||||||
|
let requestId = 0;
|
||||||
|
|
||||||
|
type WorkerRequest = {
|
||||||
|
resolve: (data: any) => void;
|
||||||
|
reject: (error: Error) => void;
|
||||||
|
};
|
||||||
|
let initPromise: Promise<void> | null = null;
|
||||||
|
const pending = new Map<number, WorkerRequest>();
|
||||||
|
|
||||||
|
export function initWorker(): Promise<void> {
|
||||||
|
if (initPromise) return initPromise;
|
||||||
|
|
||||||
|
initPromise = new Promise((resolve, reject) => {
|
||||||
|
worker.onmessage = (e: MessageEvent) => {
|
||||||
|
console.log("Handling worker output");
|
||||||
|
const msg = e.data;
|
||||||
|
|
||||||
|
if (msg.type === 'ready') {
|
||||||
|
// Готов — запрос init уже обработан
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingReq = pending.get(msg.id);
|
||||||
|
if (!pendingReq) return;
|
||||||
|
pending.delete(msg.id);
|
||||||
|
|
||||||
|
if (msg.type == "success") {
|
||||||
|
pendingReq.resolve(msg.data);
|
||||||
|
} else {
|
||||||
|
console.log(msg)
|
||||||
|
pendingReq.reject(new Error(msg.error || 'Неизвестная ошибка Worker'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.onerror = (err) => {
|
||||||
|
console.error('[SQLite Worker] Ошибка:', err);
|
||||||
|
reject(new Error('Ошибка Worker'));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Отправляем init
|
||||||
|
const id = ++requestId;
|
||||||
|
pending.set(id, { resolve, reject });
|
||||||
|
worker.postMessage({ type: 'start', id });
|
||||||
|
});
|
||||||
|
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendToWorker(type: string, payload?: any): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!worker) {
|
||||||
|
reject(new Error('Worker не создан'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = ++requestId;
|
||||||
|
pending.set(id, { resolve, reject });
|
||||||
|
|
||||||
|
worker.postMessage({ type, id, ...payload });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function query(sql: string, params?: any[]): Promise<any[]> {
|
||||||
|
const result = await sendToWorker('query', { sql, params });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function command(sql: string, params?: any[]): Promise<void> {
|
||||||
|
await sendToWorker('command', { sql, params });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function closeDb(): Promise<void> {
|
||||||
|
await sendToWorker('close');
|
||||||
|
worker.terminate();
|
||||||
|
}
|
||||||
Reference in new issue
Block a user