yomitan-core 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{anki-note-service-DFsbKoVZ.cjs → anki-note-service-C4DrghzW.cjs} +2 -2
- package/dist/anki-note-service-C4DrghzW.cjs.map +1 -0
- package/dist/anki-note-service-D9J02WC6.d.cts.map +1 -1
- package/dist/{anki-note-service-C-QKjTh0.js → anki-note-service-DFfCiz9O.js} +2 -2
- package/dist/anki-note-service-DFfCiz9O.js.map +1 -0
- package/dist/anki.cjs +3 -3
- package/dist/anki.js +3 -3
- package/dist/backend-07mdJJW2.d.ts +34 -0
- package/dist/backend-07mdJJW2.d.ts.map +1 -0
- package/dist/backend-B8h0EWrF.d.cts +34 -0
- package/dist/backend-B8h0EWrF.d.cts.map +1 -0
- package/dist/database/node-sqlite.cjs +504 -0
- package/dist/database/node-sqlite.cjs.map +1 -0
- package/dist/database/node-sqlite.d.cts +51 -0
- package/dist/database/node-sqlite.d.cts.map +1 -0
- package/dist/database/node-sqlite.d.ts +51 -0
- package/dist/database/node-sqlite.d.ts.map +1 -0
- package/dist/database/node-sqlite.js +501 -0
- package/dist/database/node-sqlite.js.map +1 -0
- package/dist/database.d.cts +3 -2
- package/dist/database.d.ts +3 -2
- package/dist/debug-DsxOLdQ6.cjs.map +1 -1
- package/dist/debug-GKN7L50t.js.map +1 -1
- package/dist/dictionary-database-BcGJ3l6w.js.map +1 -1
- package/dist/dictionary-database-C7c08nXT.cjs.map +1 -1
- package/dist/{dictionary-database-DpMxja_X.d.cts → dictionary-database-DGIXks-8.d.cts} +3 -2
- package/dist/dictionary-database-DGIXks-8.d.cts.map +1 -0
- package/dist/{dictionary-database-DPUaJQOx.d.ts → dictionary-database-VKx3UEgB.d.ts} +3 -2
- package/dist/dictionary-database-VKx3UEgB.d.ts.map +1 -0
- package/dist/dictionary-importer-CtS5tiL3.js.map +1 -1
- package/dist/dictionary-importer-DWMTH8fo.cjs.map +1 -1
- package/dist/dictionary-update-checker-B7RAjO4W.cjs.map +1 -1
- package/dist/dictionary-update-checker-FftmgW-j.js.map +1 -1
- package/dist/{display-generator-DND4pNyJ.cjs → display-generator-Ca2Jl4vd.cjs} +3 -3
- package/dist/{display-generator-DZrA0rxi.cjs → display-generator-Cr9sc5eH.cjs} +2 -2
- package/dist/{display-generator-DZrA0rxi.cjs.map → display-generator-Cr9sc5eH.cjs.map} +1 -1
- package/dist/display-generator-DLKHZGCp.js +10 -0
- package/dist/{display-generator-1zmUYl1R.js → display-generator-DSWDUlLo.js} +3 -3
- package/dist/{display-generator-1zmUYl1R.js.map → display-generator-DSWDUlLo.js.map} +1 -1
- package/dist/frequency-ranking-BshxWSpt.js.map +1 -1
- package/dist/frequency-ranking-CgEOUabZ.cjs.map +1 -1
- package/dist/{furigana-Bubb1FHO.cjs → furigana-Cagjg53_.cjs} +2 -2
- package/dist/{furigana-Bubb1FHO.cjs.map → furigana-Cagjg53_.cjs.map} +1 -1
- package/dist/furigana-D-mrmKWu.js +5 -0
- package/dist/furigana-DI357F6D.cjs +5 -0
- package/dist/{furigana-CXdd3NuU.js → furigana-RwtSF-gP.js} +2 -2
- package/dist/{furigana-CXdd3NuU.js.map → furigana-RwtSF-gP.js.map} +1 -1
- package/dist/import.d.cts +3 -3
- package/dist/import.d.cts.map +1 -1
- package/dist/import.d.ts +3 -3
- package/dist/import.d.ts.map +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/{japanese-nDDKabie.cjs → japanese-Kil-z4yh.cjs} +5 -5
- package/dist/{japanese-nDDKabie.cjs.map → japanese-Kil-z4yh.cjs.map} +1 -1
- package/dist/{japanese-DI8rL8f6.js → japanese-yAHTjQ1R.js} +2 -2
- package/dist/{japanese-DI8rL8f6.js.map → japanese-yAHTjQ1R.js.map} +1 -1
- package/dist/language.cjs +3 -3
- package/dist/language.d.cts +1 -1
- package/dist/language.d.ts +1 -1
- package/dist/language.d.ts.map +1 -1
- package/dist/language.js +3 -3
- package/dist/lookup.cjs +4 -4
- package/dist/lookup.d.cts +3 -3
- package/dist/lookup.d.cts.map +1 -1
- package/dist/lookup.d.ts +3 -3
- package/dist/lookup.d.ts.map +1 -1
- package/dist/lookup.js +4 -4
- package/dist/{multi-language-transformer-DN8B556n.d.ts → multi-language-transformer-CM6OxCAj.d.ts} +1 -1
- package/dist/{multi-language-transformer-DN8B556n.d.ts.map → multi-language-transformer-CM6OxCAj.d.ts.map} +1 -1
- package/dist/{multi-language-transformer-BINUZznN.cjs → multi-language-transformer-DUn7bpiO.cjs} +2140 -2140
- package/dist/{multi-language-transformer-BINUZznN.cjs.map → multi-language-transformer-DUn7bpiO.cjs.map} +1 -1
- package/dist/{multi-language-transformer-BxQqmnO6.d.cts → multi-language-transformer-cchZk_nI.d.cts} +1 -1
- package/dist/{multi-language-transformer-BxQqmnO6.d.cts.map → multi-language-transformer-cchZk_nI.d.cts.map} +1 -1
- package/dist/{multi-language-transformer-DaWD2kSu.js → multi-language-transformer-ud4aSIiO.js} +2130 -2130
- package/dist/{multi-language-transformer-DaWD2kSu.js.map → multi-language-transformer-ud4aSIiO.js.map} +1 -1
- package/dist/{pronunciation-generator-BNXWwIvB.js → pronunciation-generator-4wOYy1DW.js} +1 -1
- package/dist/{pronunciation-generator-LJ73uGt-.js → pronunciation-generator-ieUXk-ak.js} +2 -2
- package/dist/{pronunciation-generator-LJ73uGt-.js.map → pronunciation-generator-ieUXk-ak.js.map} +1 -1
- package/dist/render.cjs +3 -3
- package/dist/render.js +4 -4
- package/dist/{sentence-parser-DEWvHxh1.cjs → sentence-parser-BLKrC5Cd.cjs} +2 -2
- package/dist/sentence-parser-BLKrC5Cd.cjs.map +1 -0
- package/dist/{sentence-parser-7zZ89BMS.d.cts → sentence-parser-CBthVfqB.d.cts} +3 -3
- package/dist/sentence-parser-CBthVfqB.d.cts.map +1 -0
- package/dist/sentence-parser-CUbHj3Wj.cjs +6 -0
- package/dist/sentence-parser-CW6O9E7m.js +6 -0
- package/dist/{sentence-parser-CSMAW_v1.js → sentence-parser-Dw-yAsAf.js} +2 -2
- package/dist/sentence-parser-Dw-yAsAf.js.map +1 -0
- package/dist/{sentence-parser-CDR8v8c2.d.ts → sentence-parser-qfM_cvid.d.ts} +3 -3
- package/dist/sentence-parser-qfM_cvid.d.ts.map +1 -0
- package/dist/translator-B-HF5sof.cjs +7 -0
- package/dist/{translator-EsSp1SJh.cjs → translator-CwFgb6-j.cjs} +2 -2
- package/dist/translator-CwFgb6-j.cjs.map +1 -0
- package/dist/{translator-CVM1vCV2.js → translator-SBsF5K1s.js} +2 -2
- package/dist/{translator-EsSp1SJh.cjs.map → translator-SBsF5K1s.js.map} +1 -1
- package/dist/translator-sdQ1lwP8.js +7 -0
- package/package.json +8 -1
- package/dist/anki-note-service-C-QKjTh0.js.map +0 -1
- package/dist/anki-note-service-DFsbKoVZ.cjs.map +0 -1
- package/dist/dictionary-database-DPUaJQOx.d.ts.map +0 -1
- package/dist/dictionary-database-DpMxja_X.d.cts.map +0 -1
- package/dist/display-generator-BrImemhP.js +0 -10
- package/dist/furigana-BjsV1Wk1.cjs +0 -5
- package/dist/furigana-CWP_oNiw.js +0 -5
- package/dist/sentence-parser-7zZ89BMS.d.cts.map +0 -1
- package/dist/sentence-parser-BFDqhjbz.cjs +0 -6
- package/dist/sentence-parser-Bww16viy.js +0 -6
- package/dist/sentence-parser-CDR8v8c2.d.ts.map +0 -1
- package/dist/sentence-parser-CSMAW_v1.js.map +0 -1
- package/dist/sentence-parser-DEWvHxh1.cjs.map +0 -1
- package/dist/translator-Bq_7U870.cjs +0 -7
- package/dist/translator-CVM1vCV2.js.map +0 -1
- package/dist/translator-DElwfWOM.js +0 -7
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import "../dictionary-o42ErAc-.js";
|
|
2
|
+
import { DeleteDictionaryProgressCallback, DictionaryAndQueryRequest, DictionaryCounts, DictionarySet, KanjiEntry, KanjiMeta, MatchType, Media$1 as Media, MediaRequest, ObjectStoreName, Summary, Tag$2 as Tag, TermEntry, TermExactRequest, TermMeta } from "../dictionary-importer-BUhx1hez.js";
|
|
3
|
+
import { DictionaryDatabaseBackend } from "../backend-07mdJJW2.js";
|
|
4
|
+
|
|
5
|
+
//#region src/database/node-sqlite-dictionary-database.d.ts
|
|
6
|
+
type NodeSqliteDictionaryDBOptions = {
|
|
7
|
+
path: string;
|
|
8
|
+
};
|
|
9
|
+
declare class NodeSqliteDictionaryDB implements DictionaryDatabaseBackend {
|
|
10
|
+
private _path;
|
|
11
|
+
private _db;
|
|
12
|
+
private _isOpen;
|
|
13
|
+
constructor(options: NodeSqliteDictionaryDBOptions | string);
|
|
14
|
+
open(): Promise<void>;
|
|
15
|
+
close(): void;
|
|
16
|
+
get isOpen(): boolean;
|
|
17
|
+
purge(): Promise<boolean>;
|
|
18
|
+
deleteDictionary(dictionaryName: string, onProgress?: DeleteDictionaryProgressCallback): Promise<void>;
|
|
19
|
+
findTermsBulk(termList: string[], dictionaries: DictionarySet, matchType: MatchType): Promise<TermEntry[]>;
|
|
20
|
+
findTermsExactBulk(termList: TermExactRequest[], dictionaries: DictionarySet): Promise<TermEntry[]>;
|
|
21
|
+
findTermsBySequenceBulk(items: DictionaryAndQueryRequest[]): Promise<TermEntry[]>;
|
|
22
|
+
findTermMetaBulk(termList: string[], dictionaries: DictionarySet): Promise<TermMeta[]>;
|
|
23
|
+
findKanjiBulk(kanjiList: string[], dictionaries: DictionarySet): Promise<KanjiEntry[]>;
|
|
24
|
+
findKanjiMetaBulk(kanjiList: string[], dictionaries: DictionarySet): Promise<KanjiMeta[]>;
|
|
25
|
+
findTagMetaBulk(items: DictionaryAndQueryRequest[]): Promise<(Tag | undefined)[]>;
|
|
26
|
+
findTagForTitle(name: string, dictionary: string): Promise<Tag | undefined>;
|
|
27
|
+
getMedia(items: MediaRequest[]): Promise<Media[]>;
|
|
28
|
+
getDictionaryInfo(): Promise<Summary[]>;
|
|
29
|
+
getDictionaryCounts(dictionaryNames: string[], getTotal: boolean): Promise<DictionaryCounts>;
|
|
30
|
+
dictionaryExists(title: string): Promise<boolean>;
|
|
31
|
+
bulkAdd(objectStoreName: ObjectStoreName, items: unknown[], start: number, count: number): Promise<void>;
|
|
32
|
+
addWithResult(objectStoreName: ObjectStoreName, item: unknown): Promise<number>;
|
|
33
|
+
bulkUpdate(objectStoreName: ObjectStoreName, items: {
|
|
34
|
+
primaryKey: number;
|
|
35
|
+
data: unknown;
|
|
36
|
+
}[], start: number, count: number): Promise<void>;
|
|
37
|
+
private _getDb;
|
|
38
|
+
private _createSchema;
|
|
39
|
+
private _selectTerms;
|
|
40
|
+
private _selectJsonRows;
|
|
41
|
+
private _getInsertStatement;
|
|
42
|
+
private _getUpdateStatement;
|
|
43
|
+
private _createTerm;
|
|
44
|
+
private _createTermMeta;
|
|
45
|
+
private _createKanji;
|
|
46
|
+
}
|
|
47
|
+
declare function createNodeSqliteDictionaryDB(options: NodeSqliteDictionaryDBOptions | string): NodeSqliteDictionaryDB;
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { NodeSqliteDictionaryDB, createNodeSqliteDictionaryDB };
|
|
51
|
+
//# sourceMappingURL=node-sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-sqlite.d.ts","names":[],"sources":["../../src/database/node-sqlite-dictionary-database.ts"],"sourcesContent":null,"mappings":"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"}
|
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
import { stringReverse } from "../utilities-CcvCnZvO.js";
|
|
2
|
+
import { log } from "../log-C6n0pevi.js";
|
|
3
|
+
import Database from "better-sqlite3";
|
|
4
|
+
|
|
5
|
+
//#region src/database/node-sqlite-dictionary-database.ts
|
|
6
|
+
const DELETE_TARGETS = [
|
|
7
|
+
"kanji",
|
|
8
|
+
"kanjiMeta",
|
|
9
|
+
"terms",
|
|
10
|
+
"termMeta",
|
|
11
|
+
"tagMeta",
|
|
12
|
+
"media"
|
|
13
|
+
];
|
|
14
|
+
var NodeSqliteDictionaryDB = class {
|
|
15
|
+
_path;
|
|
16
|
+
_db = null;
|
|
17
|
+
_isOpen = false;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this._path = typeof options === "string" ? options : options.path;
|
|
20
|
+
}
|
|
21
|
+
async open() {
|
|
22
|
+
if (this._isOpen) return;
|
|
23
|
+
this._db = new Database(this._path);
|
|
24
|
+
this._db.pragma("journal_mode = WAL");
|
|
25
|
+
this._db.pragma("foreign_keys = ON");
|
|
26
|
+
this._createSchema();
|
|
27
|
+
this._isOpen = true;
|
|
28
|
+
}
|
|
29
|
+
close() {
|
|
30
|
+
if (this._db !== null) this._db.close();
|
|
31
|
+
this._db = null;
|
|
32
|
+
this._isOpen = false;
|
|
33
|
+
}
|
|
34
|
+
get isOpen() {
|
|
35
|
+
return this._isOpen;
|
|
36
|
+
}
|
|
37
|
+
async purge() {
|
|
38
|
+
try {
|
|
39
|
+
const db = this._getDb();
|
|
40
|
+
const purge = db.transaction(() => {
|
|
41
|
+
for (const storeName of ["dictionaries", ...DELETE_TARGETS]) {
|
|
42
|
+
db.prepare(`DELETE FROM ${storeName}`).run();
|
|
43
|
+
db.prepare("DELETE FROM sqlite_sequence WHERE name = ?").run(storeName);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
purge();
|
|
47
|
+
return true;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
log.error(e);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async deleteDictionary(dictionaryName, onProgress) {
|
|
54
|
+
const db = this._getDb();
|
|
55
|
+
const progressData = {
|
|
56
|
+
count: 0,
|
|
57
|
+
processed: 0,
|
|
58
|
+
storeCount: DELETE_TARGETS.length + 1,
|
|
59
|
+
storesProcesed: 0
|
|
60
|
+
};
|
|
61
|
+
for (const storeName of DELETE_TARGETS) {
|
|
62
|
+
const ids = db.prepare(`SELECT id FROM ${storeName} WHERE dictionary = ? ORDER BY id`).all(dictionaryName).map((row) => row.id);
|
|
63
|
+
progressData.storesProcesed += 1;
|
|
64
|
+
progressData.count += ids.length;
|
|
65
|
+
onProgress?.(progressData);
|
|
66
|
+
const deleteById = db.prepare(`DELETE FROM ${storeName} WHERE id = ?`);
|
|
67
|
+
const deleteBatch = db.transaction((batch) => {
|
|
68
|
+
for (const id of batch) deleteById.run(id);
|
|
69
|
+
});
|
|
70
|
+
const batchSize = 1e3;
|
|
71
|
+
for (let i = 0; i < ids.length; i += batchSize) {
|
|
72
|
+
const batch = ids.slice(i, i + batchSize);
|
|
73
|
+
deleteBatch(batch);
|
|
74
|
+
progressData.processed += batch.length;
|
|
75
|
+
onProgress?.(progressData);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
db.prepare("DELETE FROM dictionaries WHERE title = ?").run(dictionaryName);
|
|
79
|
+
progressData.storesProcesed += 1;
|
|
80
|
+
onProgress?.(progressData);
|
|
81
|
+
}
|
|
82
|
+
async findTermsBulk(termList, dictionaries, matchType) {
|
|
83
|
+
if (termList.length === 0) return [];
|
|
84
|
+
const visited = new Set();
|
|
85
|
+
const results = [];
|
|
86
|
+
const indexNames = matchType === "suffix" ? ["expressionReverse", "readingReverse"] : ["expression", "reading"];
|
|
87
|
+
for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {
|
|
88
|
+
const item = termList[itemIndex];
|
|
89
|
+
for (let indexIndex = 0; indexIndex < indexNames.length; indexIndex += 1) {
|
|
90
|
+
const indexName = indexNames[indexIndex];
|
|
91
|
+
const queryText = matchType === "suffix" ? stringReverse(item) : item;
|
|
92
|
+
const rows = matchType === "exact" ? this._selectTerms(`${indexName} = ?`, [queryText]) : this._selectTerms(`${indexName} LIKE ? ESCAPE '\\'`, [`${escapeLike(queryText)}%`]).filter((row) => String(row[indexName] ?? "").startsWith(queryText));
|
|
93
|
+
for (const row of rows) {
|
|
94
|
+
if (!dictionaries.has(row.dictionary) || visited.has(row.id)) continue;
|
|
95
|
+
visited.add(row.id);
|
|
96
|
+
const matchSourceIsTerm = indexIndex === 0;
|
|
97
|
+
const matchSource = matchSourceIsTerm ? "term" : "reading";
|
|
98
|
+
const actualMatchType = (matchSourceIsTerm ? row.expression : row.reading) === item ? "exact" : matchType;
|
|
99
|
+
results.push(this._createTerm(matchSource, actualMatchType, row, itemIndex));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return results;
|
|
104
|
+
}
|
|
105
|
+
async findTermsExactBulk(termList, dictionaries) {
|
|
106
|
+
const results = [];
|
|
107
|
+
for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {
|
|
108
|
+
const item = termList[itemIndex];
|
|
109
|
+
const rows = this._selectTerms("expression = ?", [item.term]);
|
|
110
|
+
for (const row of rows) {
|
|
111
|
+
if (row.reading !== item.reading || !dictionaries.has(row.dictionary)) continue;
|
|
112
|
+
results.push(this._createTerm("term", "exact", row, itemIndex));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return results;
|
|
116
|
+
}
|
|
117
|
+
async findTermsBySequenceBulk(items) {
|
|
118
|
+
const results = [];
|
|
119
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
|
|
120
|
+
const item = items[itemIndex];
|
|
121
|
+
const rows = this._selectTerms("sequence = ?", [item.query]);
|
|
122
|
+
for (const row of rows) {
|
|
123
|
+
if (row.dictionary !== item.dictionary) continue;
|
|
124
|
+
results.push(this._createTerm("sequence", "exact", row, itemIndex));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
async findTermMetaBulk(termList, dictionaries) {
|
|
130
|
+
const results = [];
|
|
131
|
+
for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {
|
|
132
|
+
const rows = this._selectJsonRows("termMeta", "expression = ?", [termList[itemIndex]]);
|
|
133
|
+
for (const row of rows) if (dictionaries.has(row.dictionary)) results.push(this._createTermMeta(row, itemIndex));
|
|
134
|
+
}
|
|
135
|
+
return results;
|
|
136
|
+
}
|
|
137
|
+
async findKanjiBulk(kanjiList, dictionaries) {
|
|
138
|
+
const results = [];
|
|
139
|
+
for (let itemIndex = 0; itemIndex < kanjiList.length; itemIndex += 1) {
|
|
140
|
+
const rows = this._selectJsonRows("kanji", "character = ?", [kanjiList[itemIndex]]);
|
|
141
|
+
for (const row of rows) if (dictionaries.has(row.dictionary)) results.push(this._createKanji(row, itemIndex));
|
|
142
|
+
}
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
async findKanjiMetaBulk(kanjiList, dictionaries) {
|
|
146
|
+
const results = [];
|
|
147
|
+
for (let itemIndex = 0; itemIndex < kanjiList.length; itemIndex += 1) {
|
|
148
|
+
const rows = this._selectJsonRows("kanjiMeta", "character = ?", [kanjiList[itemIndex]]);
|
|
149
|
+
for (const row of rows) {
|
|
150
|
+
if (!dictionaries.has(row.dictionary)) continue;
|
|
151
|
+
results.push({
|
|
152
|
+
index: itemIndex,
|
|
153
|
+
character: row.character,
|
|
154
|
+
mode: row.mode,
|
|
155
|
+
data: row.data,
|
|
156
|
+
dictionary: row.dictionary
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return results;
|
|
161
|
+
}
|
|
162
|
+
async findTagMetaBulk(items) {
|
|
163
|
+
const results = new Array(items.length);
|
|
164
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
165
|
+
const item = items[i];
|
|
166
|
+
results[i] = this._selectJsonRows("tagMeta", "name = ? AND dictionary = ?", [item.query, item.dictionary])[0];
|
|
167
|
+
}
|
|
168
|
+
return results;
|
|
169
|
+
}
|
|
170
|
+
async findTagForTitle(name, dictionary) {
|
|
171
|
+
return this._selectJsonRows("tagMeta", "name = ? AND dictionary = ?", [name, dictionary])[0];
|
|
172
|
+
}
|
|
173
|
+
async getMedia(items) {
|
|
174
|
+
const results = [];
|
|
175
|
+
const db = this._getDb();
|
|
176
|
+
const statement = db.prepare("SELECT * FROM media WHERE path = ? ORDER BY id");
|
|
177
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
|
|
178
|
+
const item = items[itemIndex];
|
|
179
|
+
const rows = statement.all(item.path);
|
|
180
|
+
for (const row of rows) {
|
|
181
|
+
if (row.dictionary !== item.dictionary || typeof row.content === "undefined") continue;
|
|
182
|
+
results.push({
|
|
183
|
+
index: itemIndex,
|
|
184
|
+
dictionary: row.dictionary,
|
|
185
|
+
path: item.path,
|
|
186
|
+
mediaType: row.mediaType,
|
|
187
|
+
width: row.width,
|
|
188
|
+
height: row.height,
|
|
189
|
+
content: bufferToArrayBuffer(row.content)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return results;
|
|
194
|
+
}
|
|
195
|
+
async getDictionaryInfo() {
|
|
196
|
+
return this._selectJsonRows("dictionaries");
|
|
197
|
+
}
|
|
198
|
+
async getDictionaryCounts(dictionaryNames, getTotal) {
|
|
199
|
+
const db = this._getDb();
|
|
200
|
+
const storeNames = [
|
|
201
|
+
"kanji",
|
|
202
|
+
"kanjiMeta",
|
|
203
|
+
"terms",
|
|
204
|
+
"termMeta",
|
|
205
|
+
"tagMeta",
|
|
206
|
+
"media"
|
|
207
|
+
];
|
|
208
|
+
const counts = [];
|
|
209
|
+
let total = null;
|
|
210
|
+
if (getTotal) {
|
|
211
|
+
total = {};
|
|
212
|
+
for (const storeName of storeNames) total[storeName] = getCount(db, storeName);
|
|
213
|
+
}
|
|
214
|
+
for (const dictionaryName of dictionaryNames) {
|
|
215
|
+
const countGroup = {};
|
|
216
|
+
for (const storeName of storeNames) countGroup[storeName] = getCount(db, storeName, dictionaryName);
|
|
217
|
+
counts.push(countGroup);
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
total,
|
|
221
|
+
counts
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
async dictionaryExists(title) {
|
|
225
|
+
const row = this._getDb().prepare("SELECT id FROM dictionaries WHERE title = ? LIMIT 1").get(title);
|
|
226
|
+
return typeof row !== "undefined";
|
|
227
|
+
}
|
|
228
|
+
async bulkAdd(objectStoreName, items, start, count) {
|
|
229
|
+
if (start + count > items.length) count = items.length - start;
|
|
230
|
+
if (count <= 0) return;
|
|
231
|
+
const batch = items.slice(start, start + count);
|
|
232
|
+
const insert = this._getInsertStatement(objectStoreName);
|
|
233
|
+
const addBatch = this._getDb().transaction((entries) => {
|
|
234
|
+
for (const item of entries) insert(item);
|
|
235
|
+
});
|
|
236
|
+
addBatch(batch);
|
|
237
|
+
}
|
|
238
|
+
async addWithResult(objectStoreName, item) {
|
|
239
|
+
return this._getInsertStatement(objectStoreName)(item);
|
|
240
|
+
}
|
|
241
|
+
async bulkUpdate(objectStoreName, items, start, count) {
|
|
242
|
+
if (start + count > items.length) count = items.length - start;
|
|
243
|
+
if (count <= 0) return;
|
|
244
|
+
const batch = items.slice(start, start + count);
|
|
245
|
+
const update = this._getUpdateStatement(objectStoreName);
|
|
246
|
+
const updateBatch = this._getDb().transaction((entries) => {
|
|
247
|
+
for (const item of entries) update(item.primaryKey, item.data);
|
|
248
|
+
});
|
|
249
|
+
updateBatch(batch);
|
|
250
|
+
}
|
|
251
|
+
_getDb() {
|
|
252
|
+
if (this._db === null) throw new Error("Database is not ready");
|
|
253
|
+
return this._db;
|
|
254
|
+
}
|
|
255
|
+
_createSchema() {
|
|
256
|
+
const db = this._getDb();
|
|
257
|
+
db.exec(`
|
|
258
|
+
CREATE TABLE IF NOT EXISTS dictionaries (
|
|
259
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
260
|
+
title TEXT NOT NULL,
|
|
261
|
+
version INTEGER,
|
|
262
|
+
data TEXT NOT NULL
|
|
263
|
+
);
|
|
264
|
+
CREATE INDEX IF NOT EXISTS dictionaries_title_idx ON dictionaries(title);
|
|
265
|
+
|
|
266
|
+
CREATE TABLE IF NOT EXISTS terms (
|
|
267
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
268
|
+
dictionary TEXT NOT NULL,
|
|
269
|
+
expression TEXT NOT NULL,
|
|
270
|
+
reading TEXT NOT NULL,
|
|
271
|
+
sequence INTEGER,
|
|
272
|
+
expressionReverse TEXT,
|
|
273
|
+
readingReverse TEXT,
|
|
274
|
+
data TEXT NOT NULL
|
|
275
|
+
);
|
|
276
|
+
CREATE INDEX IF NOT EXISTS terms_expression_idx ON terms(expression);
|
|
277
|
+
CREATE INDEX IF NOT EXISTS terms_reading_idx ON terms(reading);
|
|
278
|
+
CREATE INDEX IF NOT EXISTS terms_sequence_idx ON terms(sequence);
|
|
279
|
+
CREATE INDEX IF NOT EXISTS terms_expression_reverse_idx ON terms(expressionReverse);
|
|
280
|
+
CREATE INDEX IF NOT EXISTS terms_reading_reverse_idx ON terms(readingReverse);
|
|
281
|
+
CREATE INDEX IF NOT EXISTS terms_dictionary_idx ON terms(dictionary);
|
|
282
|
+
|
|
283
|
+
CREATE TABLE IF NOT EXISTS termMeta (
|
|
284
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
285
|
+
dictionary TEXT NOT NULL,
|
|
286
|
+
expression TEXT NOT NULL,
|
|
287
|
+
mode TEXT NOT NULL,
|
|
288
|
+
data TEXT NOT NULL
|
|
289
|
+
);
|
|
290
|
+
CREATE INDEX IF NOT EXISTS term_meta_expression_idx ON termMeta(expression);
|
|
291
|
+
CREATE INDEX IF NOT EXISTS term_meta_dictionary_idx ON termMeta(dictionary);
|
|
292
|
+
|
|
293
|
+
CREATE TABLE IF NOT EXISTS kanji (
|
|
294
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
295
|
+
dictionary TEXT NOT NULL,
|
|
296
|
+
character TEXT NOT NULL,
|
|
297
|
+
data TEXT NOT NULL
|
|
298
|
+
);
|
|
299
|
+
CREATE INDEX IF NOT EXISTS kanji_character_idx ON kanji(character);
|
|
300
|
+
CREATE INDEX IF NOT EXISTS kanji_dictionary_idx ON kanji(dictionary);
|
|
301
|
+
|
|
302
|
+
CREATE TABLE IF NOT EXISTS kanjiMeta (
|
|
303
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
304
|
+
dictionary TEXT NOT NULL,
|
|
305
|
+
character TEXT NOT NULL,
|
|
306
|
+
mode TEXT NOT NULL,
|
|
307
|
+
data TEXT NOT NULL
|
|
308
|
+
);
|
|
309
|
+
CREATE INDEX IF NOT EXISTS kanji_meta_character_idx ON kanjiMeta(character);
|
|
310
|
+
CREATE INDEX IF NOT EXISTS kanji_meta_dictionary_idx ON kanjiMeta(dictionary);
|
|
311
|
+
|
|
312
|
+
CREATE TABLE IF NOT EXISTS tagMeta (
|
|
313
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
314
|
+
dictionary TEXT NOT NULL,
|
|
315
|
+
name TEXT NOT NULL,
|
|
316
|
+
data TEXT NOT NULL
|
|
317
|
+
);
|
|
318
|
+
CREATE INDEX IF NOT EXISTS tag_meta_name_idx ON tagMeta(name);
|
|
319
|
+
CREATE INDEX IF NOT EXISTS tag_meta_dictionary_idx ON tagMeta(dictionary);
|
|
320
|
+
|
|
321
|
+
CREATE TABLE IF NOT EXISTS media (
|
|
322
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
323
|
+
dictionary TEXT NOT NULL,
|
|
324
|
+
path TEXT NOT NULL,
|
|
325
|
+
mediaType TEXT NOT NULL,
|
|
326
|
+
width INTEGER NOT NULL,
|
|
327
|
+
height INTEGER NOT NULL,
|
|
328
|
+
content BLOB NOT NULL
|
|
329
|
+
);
|
|
330
|
+
CREATE INDEX IF NOT EXISTS media_path_idx ON media(path);
|
|
331
|
+
CREATE INDEX IF NOT EXISTS media_dictionary_idx ON media(dictionary);
|
|
332
|
+
`);
|
|
333
|
+
}
|
|
334
|
+
_selectTerms(whereClause, parameters) {
|
|
335
|
+
return this._selectJsonRows("terms", whereClause, parameters);
|
|
336
|
+
}
|
|
337
|
+
_selectJsonRows(table, whereClause, parameters = []) {
|
|
338
|
+
const sql = `SELECT id, data FROM ${table}${whereClause ? ` WHERE ${whereClause}` : ""} ORDER BY id`;
|
|
339
|
+
return this._getDb().prepare(sql).all(...parameters).map((row) => ({
|
|
340
|
+
...parseJsonObject(row.data),
|
|
341
|
+
id: row.id
|
|
342
|
+
}));
|
|
343
|
+
}
|
|
344
|
+
_getInsertStatement(objectStoreName) {
|
|
345
|
+
const db = this._getDb();
|
|
346
|
+
switch (objectStoreName) {
|
|
347
|
+
case "dictionaries": {
|
|
348
|
+
const statement = db.prepare("INSERT INTO dictionaries (title, version, data) VALUES (?, ?, ?)");
|
|
349
|
+
return (item) => {
|
|
350
|
+
const row = item;
|
|
351
|
+
return Number(statement.run(row.title, row.version, JSON.stringify(row)).lastInsertRowid);
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
case "terms": {
|
|
355
|
+
const statement = db.prepare(`INSERT INTO terms
|
|
356
|
+
(dictionary, expression, reading, sequence, expressionReverse, readingReverse, data)
|
|
357
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`);
|
|
358
|
+
return (item) => {
|
|
359
|
+
const row = item;
|
|
360
|
+
return Number(statement.run(row.dictionary, row.expression, row.reading, row.sequence ?? null, row.expressionReverse ?? null, row.readingReverse ?? null, JSON.stringify(row)).lastInsertRowid);
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
case "termMeta": {
|
|
364
|
+
const statement = db.prepare("INSERT INTO termMeta (dictionary, expression, mode, data) VALUES (?, ?, ?, ?)");
|
|
365
|
+
return (item) => {
|
|
366
|
+
const row = item;
|
|
367
|
+
return Number(statement.run(row.dictionary, row.expression, row.mode, JSON.stringify(row)).lastInsertRowid);
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
case "kanji": {
|
|
371
|
+
const statement = db.prepare("INSERT INTO kanji (dictionary, character, data) VALUES (?, ?, ?)");
|
|
372
|
+
return (item) => {
|
|
373
|
+
const row = item;
|
|
374
|
+
return Number(statement.run(row.dictionary, row.character, JSON.stringify(row)).lastInsertRowid);
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
case "kanjiMeta": {
|
|
378
|
+
const statement = db.prepare("INSERT INTO kanjiMeta (dictionary, character, mode, data) VALUES (?, ?, ?, ?)");
|
|
379
|
+
return (item) => {
|
|
380
|
+
const row = item;
|
|
381
|
+
return Number(statement.run(row.dictionary, row.character, row.mode, JSON.stringify(row)).lastInsertRowid);
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
case "tagMeta": {
|
|
385
|
+
const statement = db.prepare("INSERT INTO tagMeta (dictionary, name, data) VALUES (?, ?, ?)");
|
|
386
|
+
return (item) => {
|
|
387
|
+
const row = item;
|
|
388
|
+
return Number(statement.run(row.dictionary, row.name, JSON.stringify(row)).lastInsertRowid);
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
case "media": {
|
|
392
|
+
const statement = db.prepare(`INSERT INTO media
|
|
393
|
+
(dictionary, path, mediaType, width, height, content)
|
|
394
|
+
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
395
|
+
return (item) => {
|
|
396
|
+
const row = item;
|
|
397
|
+
return Number(statement.run(row.dictionary, row.path, row.mediaType, row.width, row.height, Buffer.from(new Uint8Array(row.content))).lastInsertRowid);
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
_getUpdateStatement(objectStoreName) {
|
|
403
|
+
const db = this._getDb();
|
|
404
|
+
switch (objectStoreName) {
|
|
405
|
+
case "dictionaries": {
|
|
406
|
+
const statement = db.prepare("UPDATE dictionaries SET title = ?, version = ?, data = ? WHERE id = ?");
|
|
407
|
+
return (primaryKey, item) => {
|
|
408
|
+
const row = item;
|
|
409
|
+
statement.run(row.title, row.version, JSON.stringify(row), primaryKey);
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
case "terms":
|
|
413
|
+
case "termMeta":
|
|
414
|
+
case "kanji":
|
|
415
|
+
case "kanjiMeta":
|
|
416
|
+
case "tagMeta":
|
|
417
|
+
case "media": throw new Error(`Unsupported update store: ${objectStoreName}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
_createTerm(matchSource, matchType, row, index) {
|
|
421
|
+
const { sequence } = row;
|
|
422
|
+
return {
|
|
423
|
+
index,
|
|
424
|
+
matchType,
|
|
425
|
+
matchSource,
|
|
426
|
+
term: row.expression,
|
|
427
|
+
reading: row.reading,
|
|
428
|
+
definitionTags: splitField(row.definitionTags || row.tags),
|
|
429
|
+
termTags: splitField(row.termTags),
|
|
430
|
+
rules: splitField(row.rules),
|
|
431
|
+
definitions: row.glossary,
|
|
432
|
+
score: row.score,
|
|
433
|
+
dictionary: row.dictionary,
|
|
434
|
+
id: row.id,
|
|
435
|
+
sequence: typeof sequence === "number" ? sequence : -1
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
_createTermMeta(row, index) {
|
|
439
|
+
const { expression: term, mode, data, dictionary } = row;
|
|
440
|
+
switch (mode) {
|
|
441
|
+
case "freq": return {
|
|
442
|
+
index,
|
|
443
|
+
term,
|
|
444
|
+
mode,
|
|
445
|
+
data,
|
|
446
|
+
dictionary
|
|
447
|
+
};
|
|
448
|
+
case "pitch": return {
|
|
449
|
+
index,
|
|
450
|
+
term,
|
|
451
|
+
mode,
|
|
452
|
+
data,
|
|
453
|
+
dictionary
|
|
454
|
+
};
|
|
455
|
+
case "ipa": return {
|
|
456
|
+
index,
|
|
457
|
+
term,
|
|
458
|
+
mode,
|
|
459
|
+
data,
|
|
460
|
+
dictionary
|
|
461
|
+
};
|
|
462
|
+
default: throw new Error(`Unknown mode: ${mode}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
_createKanji(row, index) {
|
|
466
|
+
const { stats } = row;
|
|
467
|
+
return {
|
|
468
|
+
index,
|
|
469
|
+
character: row.character,
|
|
470
|
+
onyomi: splitField(row.onyomi),
|
|
471
|
+
kunyomi: splitField(row.kunyomi),
|
|
472
|
+
tags: splitField(row.tags),
|
|
473
|
+
definitions: row.meanings,
|
|
474
|
+
stats: typeof stats === "object" && stats !== null ? stats : {},
|
|
475
|
+
dictionary: row.dictionary
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
function createNodeSqliteDictionaryDB(options) {
|
|
480
|
+
return new NodeSqliteDictionaryDB(options);
|
|
481
|
+
}
|
|
482
|
+
function getCount(db, storeName, dictionaryName) {
|
|
483
|
+
const row = typeof dictionaryName === "string" ? db.prepare(`SELECT COUNT(*) AS count FROM ${storeName} WHERE dictionary = ?`).get(dictionaryName) : db.prepare(`SELECT COUNT(*) AS count FROM ${storeName}`).get();
|
|
484
|
+
return row.count;
|
|
485
|
+
}
|
|
486
|
+
function parseJsonObject(value) {
|
|
487
|
+
return JSON.parse(value ?? "{}");
|
|
488
|
+
}
|
|
489
|
+
function splitField(field) {
|
|
490
|
+
return typeof field === "string" && field.length > 0 ? field.split(" ") : [];
|
|
491
|
+
}
|
|
492
|
+
function bufferToArrayBuffer(buffer) {
|
|
493
|
+
return Uint8Array.from(buffer).buffer;
|
|
494
|
+
}
|
|
495
|
+
function escapeLike(value) {
|
|
496
|
+
return value.replace(/[\\%_]/g, (character) => `\\${character}`);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
//#endregion
|
|
500
|
+
export { NodeSqliteDictionaryDB, createNodeSqliteDictionaryDB };
|
|
501
|
+
//# sourceMappingURL=node-sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-sqlite.js","names":["DELETE_TARGETS: DictionaryDatabase.ObjectStoreName[]","options: NodeSqliteDictionaryDBOptions | string","dictionaryName: string","onProgress?: DictionaryDatabase.DeleteDictionaryProgressCallback","progressData: DictionaryDatabase.DeleteDictionaryProgressData","batch: number[]","termList: string[]","dictionaries: DictionaryDatabase.DictionarySet","matchType: DictionaryDatabase.MatchType","results: DictionaryDatabase.TermEntry[]","matchSource: DictionaryDatabase.MatchSource","actualMatchType: DictionaryDatabase.MatchType","termList: DictionaryDatabase.TermExactRequest[]","items: DictionaryDatabase.DictionaryAndQueryRequest[]","results: DictionaryDatabase.TermMeta[]","kanjiList: string[]","results: DictionaryDatabase.KanjiEntry[]","results: DictionaryDatabase.KanjiMeta[]","results: (DictionaryDatabase.Tag | undefined)[]","name: string","dictionary: string","items: DictionaryDatabase.MediaRequest[]","results: DictionaryDatabase.Media[]","dictionaryNames: string[]","getTotal: boolean","storeNames: DictionaryDatabase.ObjectStoreName[]","counts: DictionaryDatabase.DictionaryCountGroup[]","total: DictionaryDatabase.DictionaryCountGroup | null","countGroup: DictionaryDatabase.DictionaryCountGroup","title: string","objectStoreName: DictionaryDatabase.ObjectStoreName","items: unknown[]","start: number","count: number","entries: unknown[]","item: unknown","items: { primaryKey: number; data: unknown }[]","entries: { primaryKey: number; data: unknown }[]","whereClause: string","parameters: unknown[]","table: string","whereClause?: string","row: DictionaryDatabase.DatabaseTermEntryWithId","index: number","row: DictionaryDatabase.DatabaseTermMeta","row: DictionaryDatabase.DatabaseKanjiEntry","db: BetterSqliteDatabase","storeName: DictionaryDatabase.ObjectStoreName","dictionaryName?: string","value: string | undefined","field: unknown","buffer: Buffer","value: string"],"sources":["../../src/database/node-sqlite-dictionary-database.ts"],"sourcesContent":["import Database from 'better-sqlite3';\nimport type { Database as BetterSqliteDatabase } from 'better-sqlite3';\nimport type * as DictionaryDatabase from '../types/dictionary-database';\nimport type * as DictionaryImporter from '../types/dictionary-importer';\nimport { log } from '../util/log';\nimport { stringReverse } from '../util/utilities';\nimport type { DictionaryDatabaseBackend } from './backend';\n\ntype NodeSqliteDictionaryDBOptions = {\n path: string;\n};\n\ntype Row = {\n id: number;\n dictionary?: string;\n title?: string;\n data?: string;\n content?: Buffer;\n};\n\nconst DELETE_TARGETS: DictionaryDatabase.ObjectStoreName[] = [\n 'kanji',\n 'kanjiMeta',\n 'terms',\n 'termMeta',\n 'tagMeta',\n 'media',\n];\n\nexport class NodeSqliteDictionaryDB implements DictionaryDatabaseBackend {\n private _path: string;\n private _db: BetterSqliteDatabase | null = null;\n private _isOpen = false;\n\n constructor(options: NodeSqliteDictionaryDBOptions | string) {\n this._path = typeof options === 'string' ? options : options.path;\n }\n\n async open(): Promise<void> {\n if (this._isOpen) {\n return;\n }\n this._db = new Database(this._path);\n this._db.pragma('journal_mode = WAL');\n this._db.pragma('foreign_keys = ON');\n this._createSchema();\n this._isOpen = true;\n }\n\n close(): void {\n if (this._db !== null) {\n this._db.close();\n }\n this._db = null;\n this._isOpen = false;\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n async purge(): Promise<boolean> {\n try {\n const db = this._getDb();\n const purge = db.transaction(() => {\n for (const storeName of ['dictionaries', ...DELETE_TARGETS]) {\n db.prepare(`DELETE FROM ${storeName}`).run();\n // Reset rowids so reopen/repoulate behavior stays aligned with a fresh IndexedDB database.\n db.prepare('DELETE FROM sqlite_sequence WHERE name = ?').run(storeName);\n }\n });\n purge();\n return true;\n } catch (e) {\n log.error(e);\n return false;\n }\n }\n\n async deleteDictionary(\n dictionaryName: string,\n onProgress?: DictionaryDatabase.DeleteDictionaryProgressCallback,\n ): Promise<void> {\n const db = this._getDb();\n const progressData: DictionaryDatabase.DeleteDictionaryProgressData = {\n count: 0,\n processed: 0,\n storeCount: DELETE_TARGETS.length + 1,\n storesProcesed: 0,\n };\n\n for (const storeName of DELETE_TARGETS) {\n const ids = db\n .prepare(`SELECT id FROM ${storeName} WHERE dictionary = ? ORDER BY id`)\n .all(dictionaryName)\n .map((row) => (row as { id: number }).id);\n\n progressData.storesProcesed += 1;\n progressData.count += ids.length;\n onProgress?.(progressData);\n\n const deleteById = db.prepare(`DELETE FROM ${storeName} WHERE id = ?`);\n const deleteBatch = db.transaction((batch: number[]) => {\n for (const id of batch) {\n deleteById.run(id);\n }\n });\n\n const batchSize = 1000;\n for (let i = 0; i < ids.length; i += batchSize) {\n const batch = ids.slice(i, i + batchSize);\n deleteBatch(batch);\n progressData.processed += batch.length;\n onProgress?.(progressData);\n }\n }\n\n db.prepare('DELETE FROM dictionaries WHERE title = ?').run(dictionaryName);\n progressData.storesProcesed += 1;\n onProgress?.(progressData);\n }\n\n async findTermsBulk(\n termList: string[],\n dictionaries: DictionaryDatabase.DictionarySet,\n matchType: DictionaryDatabase.MatchType,\n ): Promise<DictionaryDatabase.TermEntry[]> {\n if (termList.length === 0) {\n return [];\n }\n\n const visited = new Set<number>();\n const results: DictionaryDatabase.TermEntry[] = [];\n const indexNames = matchType === 'suffix' ? ['expressionReverse', 'readingReverse'] : ['expression', 'reading'];\n\n for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {\n const item = termList[itemIndex];\n for (let indexIndex = 0; indexIndex < indexNames.length; indexIndex += 1) {\n const indexName = indexNames[indexIndex];\n const queryText = matchType === 'suffix' ? stringReverse(item) : item;\n // LIKE uses the index for the prefix scan; startsWith then trims off SQLite's default\n // case-insensitive matching so results stay byte-for-byte with the IndexedDB adapter.\n const rows =\n matchType === 'exact'\n ? this._selectTerms(`${indexName} = ?`, [queryText])\n : this._selectTerms(`${indexName} LIKE ? ESCAPE '\\\\'`, [`${escapeLike(queryText)}%`]).filter(\n (row) =>\n String(row[indexName as keyof DictionaryDatabase.DatabaseTermEntry] ?? '').startsWith(\n queryText,\n ),\n );\n\n for (const row of rows) {\n if (!dictionaries.has(row.dictionary) || visited.has(row.id)) {\n continue;\n }\n visited.add(row.id);\n\n const matchSourceIsTerm = indexIndex === 0;\n const matchSource: DictionaryDatabase.MatchSource = matchSourceIsTerm ? 'term' : 'reading';\n const actualMatchType: DictionaryDatabase.MatchType =\n (matchSourceIsTerm ? row.expression : row.reading) === item ? 'exact' : matchType;\n results.push(this._createTerm(matchSource, actualMatchType, row, itemIndex));\n }\n }\n }\n\n return results;\n }\n\n async findTermsExactBulk(\n termList: DictionaryDatabase.TermExactRequest[],\n dictionaries: DictionaryDatabase.DictionarySet,\n ): Promise<DictionaryDatabase.TermEntry[]> {\n const results: DictionaryDatabase.TermEntry[] = [];\n for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {\n const item = termList[itemIndex];\n const rows = this._selectTerms('expression = ?', [item.term]);\n for (const row of rows) {\n if (row.reading !== item.reading || !dictionaries.has(row.dictionary)) {\n continue;\n }\n results.push(this._createTerm('term', 'exact', row, itemIndex));\n }\n }\n return results;\n }\n\n async findTermsBySequenceBulk(\n items: DictionaryDatabase.DictionaryAndQueryRequest[],\n ): Promise<DictionaryDatabase.TermEntry[]> {\n const results: DictionaryDatabase.TermEntry[] = [];\n for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {\n const item = items[itemIndex];\n const rows = this._selectTerms('sequence = ?', [item.query]);\n for (const row of rows) {\n if (row.dictionary !== item.dictionary) {\n continue;\n }\n results.push(this._createTerm('sequence', 'exact', row, itemIndex));\n }\n }\n return results;\n }\n\n async findTermMetaBulk(\n termList: string[],\n dictionaries: DictionaryDatabase.DictionarySet,\n ): Promise<DictionaryDatabase.TermMeta[]> {\n const results: DictionaryDatabase.TermMeta[] = [];\n for (let itemIndex = 0; itemIndex < termList.length; itemIndex += 1) {\n const rows = this._selectJsonRows<DictionaryDatabase.DatabaseTermMeta>('termMeta', 'expression = ?', [\n termList[itemIndex],\n ]);\n for (const row of rows) {\n if (dictionaries.has(row.dictionary)) {\n results.push(this._createTermMeta(row, itemIndex));\n }\n }\n }\n return results;\n }\n\n async findKanjiBulk(\n kanjiList: string[],\n dictionaries: DictionaryDatabase.DictionarySet,\n ): Promise<DictionaryDatabase.KanjiEntry[]> {\n const results: DictionaryDatabase.KanjiEntry[] = [];\n for (let itemIndex = 0; itemIndex < kanjiList.length; itemIndex += 1) {\n const rows = this._selectJsonRows<DictionaryDatabase.DatabaseKanjiEntry>('kanji', 'character = ?', [\n kanjiList[itemIndex],\n ]);\n for (const row of rows) {\n if (dictionaries.has(row.dictionary)) {\n results.push(this._createKanji(row, itemIndex));\n }\n }\n }\n return results;\n }\n\n async findKanjiMetaBulk(\n kanjiList: string[],\n dictionaries: DictionaryDatabase.DictionarySet,\n ): Promise<DictionaryDatabase.KanjiMeta[]> {\n const results: DictionaryDatabase.KanjiMeta[] = [];\n for (let itemIndex = 0; itemIndex < kanjiList.length; itemIndex += 1) {\n const rows = this._selectJsonRows<DictionaryDatabase.DatabaseKanjiMeta>('kanjiMeta', 'character = ?', [\n kanjiList[itemIndex],\n ]);\n for (const row of rows) {\n if (!dictionaries.has(row.dictionary)) {\n continue;\n }\n results.push({\n index: itemIndex,\n character: row.character,\n mode: row.mode,\n data: row.data,\n dictionary: row.dictionary,\n });\n }\n }\n return results;\n }\n\n async findTagMetaBulk(\n items: DictionaryDatabase.DictionaryAndQueryRequest[],\n ): Promise<(DictionaryDatabase.Tag | undefined)[]> {\n const results: (DictionaryDatabase.Tag | undefined)[] = new Array(items.length);\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n results[i] = this._selectJsonRows<DictionaryDatabase.Tag>('tagMeta', 'name = ? AND dictionary = ?', [\n item.query,\n item.dictionary,\n ])[0];\n }\n return results;\n }\n\n async findTagForTitle(name: string, dictionary: string): Promise<DictionaryDatabase.Tag | undefined> {\n return this._selectJsonRows<DictionaryDatabase.Tag>('tagMeta', 'name = ? AND dictionary = ?', [\n name,\n dictionary,\n ])[0];\n }\n\n async getMedia(items: DictionaryDatabase.MediaRequest[]): Promise<DictionaryDatabase.Media[]> {\n const results: DictionaryDatabase.Media[] = [];\n const db = this._getDb();\n const statement = db.prepare('SELECT * FROM media WHERE path = ? ORDER BY id');\n\n for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {\n const item = items[itemIndex];\n const rows = statement.all(item.path) as Array<\n Row & {\n mediaType: string;\n width: number;\n height: number;\n }\n >;\n for (const row of rows) {\n if (row.dictionary !== item.dictionary || typeof row.content === 'undefined') {\n continue;\n }\n results.push({\n index: itemIndex,\n dictionary: row.dictionary,\n path: item.path,\n mediaType: row.mediaType,\n width: row.width,\n height: row.height,\n content: bufferToArrayBuffer(row.content),\n });\n }\n }\n return results;\n }\n\n async getDictionaryInfo(): Promise<DictionaryImporter.Summary[]> {\n return this._selectJsonRows<DictionaryImporter.Summary>('dictionaries');\n }\n\n async getDictionaryCounts(\n dictionaryNames: string[],\n getTotal: boolean,\n ): Promise<DictionaryDatabase.DictionaryCounts> {\n const db = this._getDb();\n const storeNames: DictionaryDatabase.ObjectStoreName[] = [\n 'kanji',\n 'kanjiMeta',\n 'terms',\n 'termMeta',\n 'tagMeta',\n 'media',\n ];\n const counts: DictionaryDatabase.DictionaryCountGroup[] = [];\n\n let total: DictionaryDatabase.DictionaryCountGroup | null = null;\n if (getTotal) {\n total = {};\n for (const storeName of storeNames) {\n total[storeName] = getCount(db, storeName);\n }\n }\n\n for (const dictionaryName of dictionaryNames) {\n const countGroup: DictionaryDatabase.DictionaryCountGroup = {};\n for (const storeName of storeNames) {\n countGroup[storeName] = getCount(db, storeName, dictionaryName);\n }\n counts.push(countGroup);\n }\n\n return { total, counts };\n }\n\n async dictionaryExists(title: string): Promise<boolean> {\n const row = this._getDb().prepare('SELECT id FROM dictionaries WHERE title = ? LIMIT 1').get(title);\n return typeof row !== 'undefined';\n }\n\n async bulkAdd(\n objectStoreName: DictionaryDatabase.ObjectStoreName,\n items: unknown[],\n start: number,\n count: number,\n ): Promise<void> {\n if (start + count > items.length) {\n count = items.length - start;\n }\n if (count <= 0) {\n return;\n }\n\n const batch = items.slice(start, start + count);\n const insert = this._getInsertStatement(objectStoreName);\n const addBatch = this._getDb().transaction((entries: unknown[]) => {\n for (const item of entries) {\n insert(item);\n }\n });\n addBatch(batch);\n }\n\n async addWithResult(objectStoreName: DictionaryDatabase.ObjectStoreName, item: unknown): Promise<number> {\n return this._getInsertStatement(objectStoreName)(item);\n }\n\n async bulkUpdate(\n objectStoreName: DictionaryDatabase.ObjectStoreName,\n items: { primaryKey: number; data: unknown }[],\n start: number,\n count: number,\n ): Promise<void> {\n if (start + count > items.length) {\n count = items.length - start;\n }\n if (count <= 0) {\n return;\n }\n\n const batch = items.slice(start, start + count);\n const update = this._getUpdateStatement(objectStoreName);\n const updateBatch = this._getDb().transaction((entries: { primaryKey: number; data: unknown }[]) => {\n for (const item of entries) {\n update(item.primaryKey, item.data);\n }\n });\n updateBatch(batch);\n }\n\n private _getDb(): BetterSqliteDatabase {\n if (this._db === null) {\n throw new Error('Database is not ready');\n }\n return this._db;\n }\n\n private _createSchema(): void {\n const db = this._getDb();\n db.exec(`\n CREATE TABLE IF NOT EXISTS dictionaries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n version INTEGER,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS dictionaries_title_idx ON dictionaries(title);\n\n CREATE TABLE IF NOT EXISTS terms (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n expression TEXT NOT NULL,\n reading TEXT NOT NULL,\n sequence INTEGER,\n expressionReverse TEXT,\n readingReverse TEXT,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS terms_expression_idx ON terms(expression);\n CREATE INDEX IF NOT EXISTS terms_reading_idx ON terms(reading);\n CREATE INDEX IF NOT EXISTS terms_sequence_idx ON terms(sequence);\n CREATE INDEX IF NOT EXISTS terms_expression_reverse_idx ON terms(expressionReverse);\n CREATE INDEX IF NOT EXISTS terms_reading_reverse_idx ON terms(readingReverse);\n CREATE INDEX IF NOT EXISTS terms_dictionary_idx ON terms(dictionary);\n\n CREATE TABLE IF NOT EXISTS termMeta (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n expression TEXT NOT NULL,\n mode TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS term_meta_expression_idx ON termMeta(expression);\n CREATE INDEX IF NOT EXISTS term_meta_dictionary_idx ON termMeta(dictionary);\n\n CREATE TABLE IF NOT EXISTS kanji (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n character TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS kanji_character_idx ON kanji(character);\n CREATE INDEX IF NOT EXISTS kanji_dictionary_idx ON kanji(dictionary);\n\n CREATE TABLE IF NOT EXISTS kanjiMeta (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n character TEXT NOT NULL,\n mode TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS kanji_meta_character_idx ON kanjiMeta(character);\n CREATE INDEX IF NOT EXISTS kanji_meta_dictionary_idx ON kanjiMeta(dictionary);\n\n CREATE TABLE IF NOT EXISTS tagMeta (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n name TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS tag_meta_name_idx ON tagMeta(name);\n CREATE INDEX IF NOT EXISTS tag_meta_dictionary_idx ON tagMeta(dictionary);\n\n CREATE TABLE IF NOT EXISTS media (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n dictionary TEXT NOT NULL,\n path TEXT NOT NULL,\n mediaType TEXT NOT NULL,\n width INTEGER NOT NULL,\n height INTEGER NOT NULL,\n content BLOB NOT NULL\n );\n CREATE INDEX IF NOT EXISTS media_path_idx ON media(path);\n CREATE INDEX IF NOT EXISTS media_dictionary_idx ON media(dictionary);\n `);\n }\n\n private _selectTerms(whereClause: string, parameters: unknown[]): DictionaryDatabase.DatabaseTermEntryWithId[] {\n return this._selectJsonRows<DictionaryDatabase.DatabaseTermEntryWithId>('terms', whereClause, parameters);\n }\n\n private _selectJsonRows<T>(table: string, whereClause?: string, parameters: unknown[] = []): T[] {\n const sql = `SELECT id, data FROM ${table}${whereClause ? ` WHERE ${whereClause}` : ''} ORDER BY id`;\n // Scalar columns exist for indexed lookup; the canonical object still lives in `data` so importer and\n // translator logic can reuse the existing in-memory shapes without a second SQLite-specific model.\n return (\n this._getDb()\n .prepare(sql)\n .all(...parameters) as Row[]\n ).map((row) => ({\n ...parseJsonObject<T>(row.data),\n id: row.id,\n }));\n }\n\n private _getInsertStatement(objectStoreName: DictionaryDatabase.ObjectStoreName): (item: unknown) => number {\n const db = this._getDb();\n switch (objectStoreName) {\n case 'dictionaries': {\n const statement = db.prepare('INSERT INTO dictionaries (title, version, data) VALUES (?, ?, ?)');\n return (item) => {\n const row = item as DictionaryImporter.Summary;\n return Number(statement.run(row.title, row.version, JSON.stringify(row)).lastInsertRowid);\n };\n }\n case 'terms': {\n const statement = db.prepare(\n `INSERT INTO terms\n (dictionary, expression, reading, sequence, expressionReverse, readingReverse, data)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n );\n return (item) => {\n const row = item as DictionaryDatabase.DatabaseTermEntry;\n return Number(\n statement.run(\n row.dictionary,\n row.expression,\n row.reading,\n row.sequence ?? null,\n row.expressionReverse ?? null,\n row.readingReverse ?? null,\n JSON.stringify(row),\n ).lastInsertRowid,\n );\n };\n }\n case 'termMeta': {\n const statement = db.prepare(\n 'INSERT INTO termMeta (dictionary, expression, mode, data) VALUES (?, ?, ?, ?)',\n );\n return (item) => {\n const row = item as DictionaryDatabase.DatabaseTermMeta;\n return Number(\n statement.run(row.dictionary, row.expression, row.mode, JSON.stringify(row)).lastInsertRowid,\n );\n };\n }\n case 'kanji': {\n const statement = db.prepare('INSERT INTO kanji (dictionary, character, data) VALUES (?, ?, ?)');\n return (item) => {\n const row = item as DictionaryDatabase.DatabaseKanjiEntry;\n return Number(statement.run(row.dictionary, row.character, JSON.stringify(row)).lastInsertRowid);\n };\n }\n case 'kanjiMeta': {\n const statement = db.prepare(\n 'INSERT INTO kanjiMeta (dictionary, character, mode, data) VALUES (?, ?, ?, ?)',\n );\n return (item) => {\n const row = item as DictionaryDatabase.DatabaseKanjiMeta;\n return Number(\n statement.run(row.dictionary, row.character, row.mode, JSON.stringify(row)).lastInsertRowid,\n );\n };\n }\n case 'tagMeta': {\n const statement = db.prepare('INSERT INTO tagMeta (dictionary, name, data) VALUES (?, ?, ?)');\n return (item) => {\n const row = item as DictionaryDatabase.Tag;\n return Number(statement.run(row.dictionary, row.name, JSON.stringify(row)).lastInsertRowid);\n };\n }\n case 'media': {\n const statement = db.prepare(\n `INSERT INTO media\n (dictionary, path, mediaType, width, height, content)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n return (item) => {\n const row = item as DictionaryDatabase.MediaDataArrayBufferContent;\n return Number(\n statement.run(\n row.dictionary,\n row.path,\n row.mediaType,\n row.width,\n row.height,\n Buffer.from(new Uint8Array(row.content)),\n ).lastInsertRowid,\n );\n };\n }\n }\n }\n\n private _getUpdateStatement(\n objectStoreName: DictionaryDatabase.ObjectStoreName,\n ): (primaryKey: number, item: unknown) => void {\n const db = this._getDb();\n switch (objectStoreName) {\n case 'dictionaries': {\n const statement = db.prepare('UPDATE dictionaries SET title = ?, version = ?, data = ? WHERE id = ?');\n return (primaryKey, item) => {\n const row = item as DictionaryImporter.Summary;\n statement.run(row.title, row.version, JSON.stringify(row), primaryKey);\n };\n }\n case 'terms':\n case 'termMeta':\n case 'kanji':\n case 'kanjiMeta':\n case 'tagMeta':\n case 'media':\n throw new Error(`Unsupported update store: ${objectStoreName}`);\n }\n }\n\n private _createTerm(\n matchSource: DictionaryDatabase.MatchSource,\n matchType: DictionaryDatabase.MatchType,\n row: DictionaryDatabase.DatabaseTermEntryWithId,\n index: number,\n ): DictionaryDatabase.TermEntry {\n const { sequence } = row;\n return {\n index,\n matchType,\n matchSource,\n term: row.expression,\n reading: row.reading,\n definitionTags: splitField(row.definitionTags || row.tags),\n termTags: splitField(row.termTags),\n rules: splitField(row.rules),\n definitions: row.glossary,\n score: row.score,\n dictionary: row.dictionary,\n id: row.id,\n sequence: typeof sequence === 'number' ? sequence : -1,\n };\n }\n\n private _createTermMeta(row: DictionaryDatabase.DatabaseTermMeta, index: number): DictionaryDatabase.TermMeta {\n const { expression: term, mode, data, dictionary } = row;\n switch (mode) {\n case 'freq':\n return { index, term, mode, data, dictionary };\n case 'pitch':\n return { index, term, mode, data, dictionary };\n case 'ipa':\n return { index, term, mode, data, dictionary };\n default:\n throw new Error(`Unknown mode: ${mode}`);\n }\n }\n\n private _createKanji(row: DictionaryDatabase.DatabaseKanjiEntry, index: number): DictionaryDatabase.KanjiEntry {\n const { stats } = row;\n return {\n index,\n character: row.character,\n onyomi: splitField(row.onyomi),\n kunyomi: splitField(row.kunyomi),\n tags: splitField(row.tags),\n definitions: row.meanings,\n stats: typeof stats === 'object' && stats !== null ? stats : {},\n dictionary: row.dictionary,\n };\n }\n}\n\nexport function createNodeSqliteDictionaryDB(options: NodeSqliteDictionaryDBOptions | string): NodeSqliteDictionaryDB {\n return new NodeSqliteDictionaryDB(options);\n}\n\nfunction getCount(\n db: BetterSqliteDatabase,\n storeName: DictionaryDatabase.ObjectStoreName,\n dictionaryName?: string,\n): number {\n const row =\n typeof dictionaryName === 'string'\n ? db.prepare(`SELECT COUNT(*) AS count FROM ${storeName} WHERE dictionary = ?`).get(dictionaryName)\n : db.prepare(`SELECT COUNT(*) AS count FROM ${storeName}`).get();\n return (row as { count: number }).count;\n}\n\nfunction parseJsonObject<T>(value: string | undefined): T {\n return JSON.parse(value ?? '{}') as T;\n}\n\nfunction splitField(field: unknown): string[] {\n return typeof field === 'string' && field.length > 0 ? field.split(' ') : [];\n}\n\nfunction bufferToArrayBuffer(buffer: Buffer): ArrayBuffer {\n return Uint8Array.from(buffer).buffer;\n}\n\nfunction escapeLike(value: string): string {\n return value.replace(/[\\\\%_]/g, (character) => `\\\\${character}`);\n}\n"],"mappings":"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"}
|
package/dist/database.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "./dictionary-C3FUjHaZ.cjs";
|
|
2
2
|
import "./dictionary-importer-CRUzc3YR.cjs";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { DictionaryDatabaseBackend } from "./backend-B8h0EWrF.cjs";
|
|
4
|
+
import { DictionaryDB, OBJECT_STORE_NAMES, YomitanDatabase } from "./dictionary-database-DGIXks-8.cjs";
|
|
5
|
+
export { DictionaryDB, DictionaryDatabaseBackend, OBJECT_STORE_NAMES, YomitanDatabase };
|
package/dist/database.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "./dictionary-o42ErAc-.js";
|
|
2
2
|
import "./dictionary-importer-BUhx1hez.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { DictionaryDatabaseBackend } from "./backend-07mdJJW2.js";
|
|
4
|
+
import { DictionaryDB$1 as DictionaryDB, OBJECT_STORE_NAMES$1 as OBJECT_STORE_NAMES, YomitanDatabase$1 as YomitanDatabase } from "./dictionary-database-VKx3UEgB.js";
|
|
5
|
+
export { DictionaryDB, DictionaryDatabaseBackend, OBJECT_STORE_NAMES, YomitanDatabase };
|