(refractor) timer and warm up query

This commit is contained in:
polv committed 2026-03-03 12:44:54 +07:00
1 parent 1b2ee0f691
commit d6f2b145c3
13 files changed
+288 -41

No files matched your search

+3 -1
View File
@@ -11,13 +11,15 @@
"license": "ISC", "license": "ISC",
"packageManager": "pnpm@10.30.3", "packageManager": "pnpm@10.30.3",
"dependencies": { "dependencies": {
"@types/adm-zip": "^0.5.7", "@fastify/mongodb": "^10.0.0",
"@fastify/static": "^9.0.0",
"adm-zip": "^0.5.16", "adm-zip": "^0.5.16",
"dotenv": "^17.3.1", "dotenv": "^17.3.1",
"fastify": "^5.7.4", "fastify": "^5.7.4",
"mongodb": "^7.1.0" "mongodb": "^7.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/adm-zip": "^0.5.7",
"@types/node": "^24.10.13", "@types/node": "^24.10.13",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "~5.8.3" "typescript": "~5.8.3"
+27
View File
@@ -0,0 +1,27 @@
import fastify from "fastify";
import { readdirSync } from "fs";
import path from "path";
import fastifyStatic from "@fastify/static";
const app = fastify({
logger: true,
});
const YOMITAN_PATH = path.join(__dirname, "../src-tauri/resources/yomitan/ja");
app.register(fastifyStatic, {
root: YOMITAN_PATH,
prefix: "/api/files/yomitan/ja",
});
app.get("/api/yomitan/ja/list", async () => {
return {
list: readdirSync(YOMITAN_PATH).filter((p) => p.endsWith(".zip")),
};
});
app.listen({ port: 3000 }).catch((e) => {
app.log.error(e);
process.exit(1);
});
+175 -3
View File
@@ -14,9 +14,12 @@ importers:
js-server: js-server:
dependencies: dependencies:
'@types/adm-zip': '@fastify/mongodb':
specifier: ^0.5.7 specifier: ^10.0.0
version: 0.5.7 version: 10.0.0
'@fastify/static':
specifier: ^9.0.0
version: 9.0.0
adm-zip: adm-zip:
specifier: ^0.5.16 specifier: ^0.5.16
version: 0.5.16 version: 0.5.16
@@ -30,6 +33,9 @@ importers:
specifier: ^7.1.0 specifier: ^7.1.0
version: 7.1.0 version: 7.1.0
devDependencies: devDependencies:
'@types/adm-zip':
specifier: ^0.5.7
version: 0.5.7
'@types/node': '@types/node':
specifier: ^24.10.13 specifier: ^24.10.13
version: 24.10.13 version: 24.10.13
@@ -397,6 +403,9 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@fastify/accept-negotiator@2.0.1':
resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==}
'@fastify/ajv-compiler@4.0.5': '@fastify/ajv-compiler@4.0.5':
resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==}
@@ -412,9 +421,18 @@ packages:
'@fastify/merge-json-schemas@0.2.1': '@fastify/merge-json-schemas@0.2.1':
resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
'@fastify/mongodb@10.0.0':
resolution: {integrity: sha512-BBkX8i3XjeQ2XJLLozVfYb2KF6boFqQf6UeX6f+LUWqbpnJbhD0euMqbTUiZkswgeyoydF09fq3eaCle6bQpIA==}
'@fastify/proxy-addr@5.1.0': '@fastify/proxy-addr@5.1.0':
resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==} resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
'@fastify/send@4.1.0':
resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==}
'@fastify/static@9.0.0':
resolution: {integrity: sha512-r64H8Woe/vfilg5RTy7lwWlE8ZZcTrc3kebYFMEUBrMqlydhQyoiExQXdYAy2REVpST/G35+stAM8WYp1WGmMA==}
'@floating-ui/core@1.7.4': '@floating-ui/core@1.7.4':
resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==}
@@ -446,6 +464,10 @@ packages:
'@jridgewell/trace-mapping@0.3.31': '@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@lukeed/ms@2.0.2':
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
engines: {node: '>=8'}
'@mongodb-js/saslprep@1.4.6': '@mongodb-js/saslprep@1.4.6':
resolution: {integrity: sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==} resolution: {integrity: sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==}
@@ -989,11 +1011,19 @@ packages:
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
engines: {node: '>=10', npm: '>=6'} engines: {node: '>=10', npm: '>=6'}
balanced-match@4.0.4:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
baseline-browser-mapping@2.10.0: baseline-browser-mapping@2.10.0:
resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
brace-expansion@5.0.4:
resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==}
engines: {node: 18 || 20 || >=22}
browserslist@4.28.1: browserslist@4.28.1:
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -1010,6 +1040,10 @@ packages:
caniuse-lite@1.0.30001770: caniuse-lite@1.0.30001770:
resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==} resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==}
content-disposition@1.0.1:
resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==}
engines: {node: '>=18'}
convert-source-map@1.9.0: convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
@@ -1036,6 +1070,10 @@ packages:
supports-color: supports-color:
optional: true optional: true
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dequal@2.0.3: dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -1059,6 +1097,9 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'} engines: {node: '>=6'}
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
escape-string-regexp@4.0.0: escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -1078,6 +1119,9 @@ packages:
fast-uri@3.1.0: fast-uri@3.1.0:
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
fastify-plugin@5.1.0:
resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==}
fastify@5.7.4: fastify@5.7.4:
resolution: {integrity: sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA==} resolution: {integrity: sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA==}
@@ -1115,6 +1159,10 @@ packages:
get-tsconfig@4.13.6: get-tsconfig@4.13.6:
resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==}
glob@13.0.6:
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
engines: {node: 18 || 20 || >=22}
hasown@2.0.2: hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -1122,10 +1170,17 @@ packages:
hoist-non-react-statics@3.3.2: hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
http-errors@2.0.1:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'}
import-fresh@3.3.1: import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
ipaddr.js@2.3.0: ipaddr.js@2.3.0:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@@ -1165,12 +1220,29 @@ packages:
lines-and-columns@1.2.4: lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
lru-cache@11.2.6:
resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==}
engines: {node: 20 || >=22}
lru-cache@5.1.1: lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
memory-pager@1.5.0: memory-pager@1.5.0:
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
mime@3.0.0:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'}
hasBin: true
minimatch@10.2.4:
resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==}
engines: {node: 18 || 20 || >=22}
minipass@7.1.3:
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
engines: {node: '>=16 || 14 >=14.17'}
mongodb-connection-string-url@7.0.1: mongodb-connection-string-url@7.0.1:
resolution: {integrity: sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==} resolution: {integrity: sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==}
engines: {node: '>=20.19.0'} engines: {node: '>=20.19.0'}
@@ -1234,6 +1306,10 @@ packages:
path-parse@1.0.7: path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
path-scurry@2.0.2:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22}
path-type@4.0.0: path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -1363,6 +1439,9 @@ packages:
set-cookie-parser@2.7.2: set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
sonic-boom@4.2.1: sonic-boom@4.2.1:
resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
@@ -1381,6 +1460,10 @@ packages:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'} engines: {node: '>= 10.x'}
statuses@2.0.2:
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
engines: {node: '>= 0.8'}
stylis@4.2.0: stylis@4.2.0:
resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
@@ -1400,6 +1483,10 @@ packages:
resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==}
engines: {node: '>=12'} engines: {node: '>=12'}
toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
tr46@5.1.1: tr46@5.1.1:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -1851,6 +1938,8 @@ snapshots:
'@esbuild/win32-x64@0.27.3': '@esbuild/win32-x64@0.27.3':
optional: true optional: true
'@fastify/accept-negotiator@2.0.1': {}
'@fastify/ajv-compiler@4.0.5': '@fastify/ajv-compiler@4.0.5':
dependencies: dependencies:
ajv: 8.18.0 ajv: 8.18.0
@@ -1869,11 +1958,41 @@ snapshots:
dependencies: dependencies:
dequal: 2.0.3 dequal: 2.0.3
'@fastify/mongodb@10.0.0':
dependencies:
fastify-plugin: 5.1.0
mongodb: 7.1.0
transitivePeerDependencies:
- '@aws-sdk/credential-providers'
- '@mongodb-js/zstd'
- gcp-metadata
- kerberos
- mongodb-client-encryption
- snappy
- socks
'@fastify/proxy-addr@5.1.0': '@fastify/proxy-addr@5.1.0':
dependencies: dependencies:
'@fastify/forwarded': 3.0.1 '@fastify/forwarded': 3.0.1
ipaddr.js: 2.3.0 ipaddr.js: 2.3.0
'@fastify/send@4.1.0':
dependencies:
'@lukeed/ms': 2.0.2
escape-html: 1.0.3
fast-decode-uri-component: 1.0.1
http-errors: 2.0.1
mime: 3.0.0
'@fastify/static@9.0.0':
dependencies:
'@fastify/accept-negotiator': 2.0.1
'@fastify/send': 4.1.0
content-disposition: 1.0.1
fastify-plugin: 5.1.0
fastq: 1.20.1
glob: 13.0.6
'@floating-ui/core@1.7.4': '@floating-ui/core@1.7.4':
dependencies: dependencies:
'@floating-ui/utils': 0.2.10 '@floating-ui/utils': 0.2.10
@@ -1912,6 +2031,8 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
'@lukeed/ms@2.0.2': {}
'@mongodb-js/saslprep@1.4.6': '@mongodb-js/saslprep@1.4.6':
dependencies: dependencies:
sparse-bitfield: 3.0.3 sparse-bitfield: 3.0.3
@@ -2705,8 +2826,14 @@ snapshots:
cosmiconfig: 7.1.0 cosmiconfig: 7.1.0
resolve: 1.22.11 resolve: 1.22.11
balanced-match@4.0.4: {}
baseline-browser-mapping@2.10.0: {} baseline-browser-mapping@2.10.0: {}
brace-expansion@5.0.4:
dependencies:
balanced-match: 4.0.4
browserslist@4.28.1: browserslist@4.28.1:
dependencies: dependencies:
baseline-browser-mapping: 2.10.0 baseline-browser-mapping: 2.10.0
@@ -2721,6 +2848,8 @@ snapshots:
caniuse-lite@1.0.30001770: {} caniuse-lite@1.0.30001770: {}
content-disposition@1.0.1: {}
convert-source-map@1.9.0: {} convert-source-map@1.9.0: {}
convert-source-map@2.0.0: {} convert-source-map@2.0.0: {}
@@ -2741,6 +2870,8 @@ snapshots:
dependencies: dependencies:
ms: 2.1.3 ms: 2.1.3
depd@2.0.0: {}
dequal@2.0.3: {} dequal@2.0.3: {}
dotenv@17.3.1: {} dotenv@17.3.1: {}
@@ -2782,6 +2913,8 @@ snapshots:
escalade@3.2.0: {} escalade@3.2.0: {}
escape-html@1.0.3: {}
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}
fast-decode-uri-component@1.0.1: {} fast-decode-uri-component@1.0.1: {}
@@ -2803,6 +2936,8 @@ snapshots:
fast-uri@3.1.0: {} fast-uri@3.1.0: {}
fastify-plugin@5.1.0: {}
fastify@5.7.4: fastify@5.7.4:
dependencies: dependencies:
'@fastify/ajv-compiler': 4.0.5 '@fastify/ajv-compiler': 4.0.5
@@ -2848,6 +2983,12 @@ snapshots:
dependencies: dependencies:
resolve-pkg-maps: 1.0.0 resolve-pkg-maps: 1.0.0
glob@13.0.6:
dependencies:
minimatch: 10.2.4
minipass: 7.1.3
path-scurry: 2.0.2
hasown@2.0.2: hasown@2.0.2:
dependencies: dependencies:
function-bind: 1.1.2 function-bind: 1.1.2
@@ -2856,11 +2997,21 @@ snapshots:
dependencies: dependencies:
react-is: 16.13.1 react-is: 16.13.1
http-errors@2.0.1:
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.2
toidentifier: 1.0.1
import-fresh@3.3.1: import-fresh@3.3.1:
dependencies: dependencies:
parent-module: 1.0.1 parent-module: 1.0.1
resolve-from: 4.0.0 resolve-from: 4.0.0
inherits@2.0.4: {}
ipaddr.js@2.3.0: {} ipaddr.js@2.3.0: {}
is-arrayish@0.2.1: {} is-arrayish@0.2.1: {}
@@ -2891,12 +3042,22 @@ snapshots:
lines-and-columns@1.2.4: {} lines-and-columns@1.2.4: {}
lru-cache@11.2.6: {}
lru-cache@5.1.1: lru-cache@5.1.1:
dependencies: dependencies:
yallist: 3.1.1 yallist: 3.1.1
memory-pager@1.5.0: {} memory-pager@1.5.0: {}
mime@3.0.0: {}
minimatch@10.2.4:
dependencies:
brace-expansion: 5.0.4
minipass@7.1.3: {}
mongodb-connection-string-url@7.0.1: mongodb-connection-string-url@7.0.1:
dependencies: dependencies:
'@types/whatwg-url': 13.0.0 '@types/whatwg-url': 13.0.0
@@ -2934,6 +3095,11 @@ snapshots:
path-parse@1.0.7: {} path-parse@1.0.7: {}
path-scurry@2.0.2:
dependencies:
lru-cache: 11.2.6
minipass: 7.1.3
path-type@4.0.0: {} path-type@4.0.0: {}
perfect-freehand@1.2.3: {} perfect-freehand@1.2.3: {}
@@ -3064,6 +3230,8 @@ snapshots:
set-cookie-parser@2.7.2: {} set-cookie-parser@2.7.2: {}
setprototypeof@1.2.0: {}
sonic-boom@4.2.1: sonic-boom@4.2.1:
dependencies: dependencies:
atomic-sleep: 1.0.0 atomic-sleep: 1.0.0
@@ -3078,6 +3246,8 @@ snapshots:
split2@4.2.0: {} split2@4.2.0: {}
statuses@2.0.2: {}
stylis@4.2.0: {} stylis@4.2.0: {}
supports-preserve-symlinks-flag@1.0.0: {} supports-preserve-symlinks-flag@1.0.0: {}
@@ -3093,6 +3263,8 @@ snapshots:
toad-cache@3.7.0: {} toad-cache@3.7.0: {}
toidentifier@1.0.1: {}
tr46@5.1.1: tr46@5.1.1:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
+2 -5
View File
@@ -1,11 +1,10 @@
use std::{ use std::{
fs::read_dir, fs::read_dir,
path::{Path, absolute}, path::{Path, absolute},
time::Instant,
}; };
use anyhow::{Context, Ok}; use anyhow::{Context, Ok};
use cjdic2_core::AppService; use cjdic2_core::{AppService, Timer};
mod common; mod common;
use common::get_db_dir; use common::get_db_dir;
@@ -24,16 +23,14 @@ fn main() -> Result<(), anyhow::Error> {
let p = e.path(); let p = e.path();
if p.extension().and_then(|s| s.to_str()) == Some("zip") { if p.extension().and_then(|s| s.to_str()) == Some("zip") {
let start = Instant::now(); let _timer = Timer::new(format!("zip_file: {:?}", p));
println!("zip_file: {:?}", p);
println!( println!(
"{:?}", "{:?}",
AppService::import_yomitan_zip_file(&mut writer, &p, "ja", |progress| { AppService::import_yomitan_zip_file(&mut writer, &p, "ja", |progress| {
println!("{:?}", progress); println!("{:?}", progress);
})?, })?,
); );
println!("[{:.2?}]", start.elapsed());
} else { } else {
println!("not zip_file: {:?}", p); println!("not zip_file: {:?}", p);
} }
+4 -5
View File
@@ -1,7 +1,5 @@
use std::time::Instant;
use anyhow::Ok; use anyhow::Ok;
use cjdic2_core::AppService; use cjdic2_core::{AppService, Timer};
mod common; mod common;
use common::get_db_dir; use common::get_db_dir;
@@ -9,10 +7,11 @@ use common::get_db_dir;
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
let service = AppService::new(get_db_dir())?; let service = AppService::new(get_db_dir())?;
let start = Instant::now(); {
let _timer = Timer::new("remove one".to_string());
let mut writer = service.get_yomitan_writer()?; let mut writer = service.get_yomitan_writer()?;
AppService::remove_yomitan_dictionary(&mut writer, "JMnedict")?; AppService::remove_yomitan_dictionary(&mut writer, "JMnedict")?;
println!("[{:.2?}]", start.elapsed()); }
Ok(()) Ok(())
} }
+4 -5
View File
@@ -1,7 +1,5 @@
use std::time::Instant;
use anyhow::Ok; use anyhow::Ok;
use cjdic2_core::AppService; use cjdic2_core::{AppService, Timer};
mod common; mod common;
use common::get_db_dir; use common::get_db_dir;
@@ -9,11 +7,12 @@ use common::get_db_dir;
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
let service = AppService::new(get_db_dir())?; let service = AppService::new(get_db_dir())?;
let start = Instant::now(); {
let _timer = Timer::new("Search".to_string());
let rs = service.search_yomitan("擦る", "する", 10, 0)?; let rs = service.search_yomitan("擦る", "する", 10, 0)?;
println!("{:#?}", rs); println!("{:#?}", rs);
println!("n={}", rs.len()); println!("n={}", rs.len());
println!("[{:.2?}]", start.elapsed()); }
Ok(()) Ok(())
} }
+4 -7
View File
@@ -1,9 +1,5 @@
use std::time::Instant;
use anyhow::Ok; use anyhow::Ok;
use cjdic2_core::AppService; use cjdic2_core::{AppService, Timer};
mod common; mod common;
use common::get_db_dir; use common::get_db_dir;
@@ -11,9 +7,10 @@ use common::get_db_dir;
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
let service = AppService::new(get_db_dir())?; let service = AppService::new(get_db_dir())?;
let start = Instant::now(); {
let _timer = Timer::new("update schema".to_string());
service.get_yomitan_writer()?; service.get_yomitan_writer()?;
println!("[{:.2?}]", start.elapsed()); }
Ok(()) Ok(())
} }
+8
View File
@@ -38,6 +38,7 @@ impl Database {
PRAGMA jornal_mode = WAL; PRAGMA jornal_mode = WAL;
PRAGMA synchronous = NORMAL; PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON; PRAGMA foreign_keys = ON;
PRAGMA cache_size = -131072;
", ",
)?; )?;
@@ -81,6 +82,13 @@ impl Database {
let uri = format!("file:{}?mode=ro&immutable=1", path); let uri = format!("file:{}?mode=ro&immutable=1", path);
conn.execute("ATTACH DATABASE ?1 AS yomitan", [uri])?; conn.execute("ATTACH DATABASE ?1 AS yomitan", [uri])?;
conn.execute_batch(
r"
PRAGMA yomitan.mmap_size = 3000000000; -- 3_000_000_000
",
)?;
self.yomitan_attached.store(true, Ordering::Release); self.yomitan_attached.store(true, Ordering::Release);
} }
+3 -1
View File
@@ -2,7 +2,7 @@ use rusqlite::{Result, params};
use serde::Serialize; use serde::Serialize;
use crate::{ use crate::{
CJDicError, CJDicError, Timer,
db::{Database, yomitan_writer::normalize_term}, db::{Database, yomitan_writer::normalize_term},
}; };
@@ -35,6 +35,8 @@ impl YomitanDatabase {
limit: u32, limit: u32,
offset: u32, offset: u32,
) -> Result<Vec<YomitanRow>, CJDicError> { ) -> Result<Vec<YomitanRow>, CJDicError> {
let _timer = Timer::new(format!("search_yomitan: {} {}", q_term, q_reading));
let and_or = if q_term == q_reading { "OR" } else { "AND" }; let and_or = if q_term == q_reading { "OR" } else { "AND" };
let mut new_t = String::new(); let mut new_t = String::new();
+2 -9
View File
@@ -7,11 +7,10 @@ use std::{
collections::HashMap, collections::HashMap,
io::{Cursor, Read}, io::{Cursor, Read},
path::{Path, PathBuf}, path::{Path, PathBuf},
time::Instant,
}; };
use zip::ZipArchive; use zip::ZipArchive;
use crate::CJDicError; use crate::{CJDicError, Timer};
fn blake3_hex(s: &str) -> String { fn blake3_hex(s: &str) -> String {
format!("{}", hash(s.as_bytes())) format!("{}", hash(s.as_bytes()))
@@ -274,8 +273,8 @@ impl YomitanWriter {
Callback: Fn(YomitanZipImportProgress), Callback: Fn(YomitanZipImportProgress),
{ {
let bundle_name = zip_file.file_name(); let bundle_name = zip_file.file_name();
let _timer = Timer::new(format!("Importing {}", bundle_name));
let start_time = Instant::now();
self.conn.execute_batch("PRAGMA foreign_keys = off")?; self.conn.execute_batch("PRAGMA foreign_keys = off")?;
let cursor = Cursor::new(zip_file.bytes()?); let cursor = Cursor::new(zip_file.bytes()?);
@@ -593,12 +592,6 @@ impl YomitanWriter {
tx.commit()?; tx.commit()?;
println!(
"Importing {} takes {:.2?}",
zip_file.file_name(),
start_time.elapsed()
);
self.conn.execute_batch( self.conn.execute_batch(
" "
PRAGMA foreign_keys = on; PRAGMA foreign_keys = on;
+2
View File
@@ -1,10 +1,12 @@
mod db; mod db;
mod error; mod error;
mod service; mod service;
mod util;
pub use db::{YomitanRow, YomitanZipImportProgress, YomitanZipImportResult, ZipSource}; pub use db::{YomitanRow, YomitanZipImportProgress, YomitanZipImportResult, ZipSource};
pub use error::CJDicError; pub use error::CJDicError;
pub use service::AppService; pub use service::AppService;
pub use util::Timer;
pub fn add(left: u64, right: u64) -> u64 { pub fn add(left: u64, right: u64) -> u64 {
left + right left + right
+35
View File
@@ -0,0 +1,35 @@
#[cfg(debug_assertions)]
use std::time::Instant;
#[cfg(debug_assertions)]
pub struct Timer {
start: Instant,
label: String,
}
#[cfg(debug_assertions)]
impl Timer {
pub fn new(label: String) -> Self {
Self {
start: Instant::now(),
label,
}
}
}
#[cfg(debug_assertions)]
impl Drop for Timer {
fn drop(&mut self) {
println!("[{}] {:.2?}", self.label, self.start.elapsed())
}
}
#[cfg(not(debug_assertions))]
pub struct Timer;
#[cfg(not(debug_assertions))]
impl Timer {
pub fn new(_label: String) -> Self {
Self
}
}
+19 -5
View File
@@ -45,6 +45,19 @@ function SearchPage() {
const lang = "ja-JP"; const lang = "ja-JP";
const isInit = useRef(false);
useEffect(() => {
if (isInit.current) return;
isInit.current = true;
invoke("search_yomitan", {
qTerm: "",
qReading: "",
limit: 1,
offset: 0,
});
});
useEffect(() => { useEffect(() => {
trySearch(); trySearch();
}, [q]); }, [q]);
@@ -72,6 +85,12 @@ function SearchPage() {
} }
async function runSearch(isNew = true) { async function runSearch(isNew = true) {
let norm_q = q.trim();
if (isAutoKana) {
norm_q = norm_q.replace(/n$/i, "ん").replace(/[a-z]$/i, "");
}
if (!norm_q) return;
const ender = /\p{Z}$/u.test(q) ? "" : "*"; const ender = /\p{Z}$/u.test(q) ? "" : "*";
const re = /\<(.+?)\>\[(.+?)\]/g; const re = /\<(.+?)\>\[(.+?)\]/g;
@@ -79,11 +98,6 @@ function SearchPage() {
let qTerm = ""; let qTerm = "";
let qReading = ""; let qReading = "";
let norm_q = q.trim();
if (isAutoKana) {
norm_q = norm_q.replace(/n$/i, "ん").replace(/[a-z]$/i, "");
}
norm_q.split(re).map((s, i) => { norm_q.split(re).map((s, i) => {
switch (i % 3) { switch (i % 3) {
case 1: case 1: