Digitale PSM یک برنامه رایگان و متنباز تحت وب برای مجموعههای باغبانی و کشاورزی است. با آن میتوان میزان مصرف محصولات حفاظت از گیاهان، مثل آفتکشها، را محاسبه و ثبت کرد و از سوابق خروجی گرفت. نیازی به حساب کاربری، بکاند یا فضای ابری نیست. تمام دادهها در یک فایل SQLite روی کامپیوتر کاربر میمانند و خود پایگاه داده با WebAssembly در مرورگر اجرا میشود.
در استفاده حرفهای از محصولات حفاظت از گیاهان، هر بار مصرف باید ثبت شود: نام محصول، مقدار، مساحت، گیاه، تاریخ و دوره انتظار تا برداشت. در عمل این اطلاعات اغلب در پوشههای کاغذی یا سرویسهای ابری با حساب کاربری، اشتراک و سرور دیگران نگهداری میشوند. Digitale PSM راه دیگری دارد: یک برنامه تحت وب که مثل نرمافزار روی کامپیوتر شخصی کار میکند، دادهها را بهصورت فایل نزد کاربر نگه میدارد و بدون اینترنت هم قابل استفاده است.
تصویر ۱ — صفحه شروعdigitale-psm.de، روی کامپیوتر و گوشی
ثبتنام و ورود ندارد. برنامه فقط میپرسد: پایگاه داده جدید میسازید یا فایل موجود را باز میکنید؟ این فایل یک پایگاه داده معمولی SQLite روی کامپیوتر کاربر است؛ میتوان آن را کپی کرد، نسخه پشتیبان گرفت و با هر ابزار سازگار با SQLite خواند.
امکانات برنامه
محاسبه، ثبت و گزارشگیری.
محاسبه
محاسبه میزان مصرف بر اساس مساحت یا مقدار، تبدیل واحدهای مختلف، ذخیره ترکیبهای پرکاربرد و انتخاب سریع کدهای EPPO و مراحل رشد BBCH.
ثبت سوابق
ثبت هر بار مصرف، نمایش تقویمی با فیلتر و خروجی PDF یا CSV.
دادههای رسمی مجوزها
پس از وارد کردن دادهها، پایگاه مجوزهای BVL در فایل خودتان قرار میگیرد. میتوانید بر اساس گیاه، آفت و ماده مؤثره جستجو کنید، حتی بدون اینترنت.
قابل نصب روی کامپیوتر، قابل استفاده آفلاین
نصب بهصورت برنامه دسکتاپ در Chrome و Edge، اجرا بدون اینترنت، به خاطر سپردن آخرین پایگاه داده و باز کردن فایلهای .sqlite با دوبار کلیک. امکان ثبت موقعیت GPS زمینها نیز وجود دارد.
جزئیات فنی
دادهها چطور ذخیره میشوند
روش معمول برای چنین برنامهای، یک سرور با پایگاه داده و حساب جداگانه برای هر کاربر است. من میخواستم دادهها در اختیار خود مجموعه و در یک فایل روی کامپیوترش بمانند. برای این کار، پایگاه داده باید همانجایی اجرا شود که دادهها هستند: در مرورگر.
برنامه فقط فایلهای ایستای HTML، CSS و JavaScript است که از GitHub Pages ارائه میشوند. هیچ سروری سوابق کاربران را دریافت نمیکند. SQLite به یک ماژول WebAssembly تبدیل شده است (@sqlite.org/sqlite-wasm) و همراه برنامه بستهبندی میشود. مانند فایلهای دیگر، هنگام ساخت برای آن هش و نسخه تعیین میشود. در زمان اجرا چیزی از CDN دیگران دریافت نمیشود؛ به همین دلیل پایگاه داده آفلاین هم کار میکند.
نکته مهم این است که فایل روی دیسک کاربر یک پایگاه داده واقعی SQLite است، نه یک قالب خروجی اختصاصی. هر ابزار SQLite میتواند آن را باز کند و میتوان آن را کپی کرد، پشتیبان گرفت یا به کامپیوتر دیگری برد.
۲. معماری سهلایه
پایگاه داده در رشته اصلی اجرای مرورگر کار نمیکند؛ داخل Web Worker جداگانهای اجرا میشود تا حتی هنگام وارد کردن دادههای حجیم، رابط کاربری پاسخگو بماند. ارتباط این دو بخش فقط با پیام انجام میشود.
رابط کاربری · رشته اصلی
Astro, TypeScript, Bootstrap
فرمها، تقویم، فهرستها و خروجی PDF و CSV
مدیریت وضعیت و رویدادها
ارتباط با پایگاه داده فقط از طریق پیام
نگهداری دسترسی فایل و نوشتن روی آن
⇄postMessage شناسه، مهلت پاسخ، انتقال بافرهای بزرگ
پایگاه داده · Web Worker
SQLite 3.54 با WebAssembly
ساختار داده با مهاجرت نسخهها، از user_version 1 تا 11
WAL، کلیدهای خارجی و کش صفحه ۲۰ مگابایتی
اجرای پرسوجوها، فهرستهای صفحهبندیشده و وارد کردن دادههای BVL
خروجی کامل پایگاه داده بهصورت بایت
⇄بایتها خروجی · ورودی
ذخیرهسازی · نزد کاربر
یک فایل .sqlite
File System Access API، با نگهداری دسترسی فایل در IndexedDB برای شروع خودکار
حالت OPFS، اگر مرورگر اجازه دهد
روشهای جایگزین: فایل JSON، localStorage و حافظه
۳. ذخیرهسازی، مرحله به مرحله
یک ورودی، مثلاً ثبت مصرف جدید، بهصورت پیام به worker فرستاده میشود. هر پیام شناسه و مهلت پاسخ دارد و نتیجه بهصورت غیرهمزمان برمیگردد.
worker داده را در SQLite مینویسد. پایگاه داده در حافظه worker قرار دارد یا، اگر مرورگر اجازه دهد، در فضای فایل خصوصی مبدأ، یعنی Origin Private File System (OPFS).
سپس worker کل پایگاه داده را به مجموعهای از بایتها تبدیل میکند (sqlite3_js_db_export) و بافر را بدون کپی کردن، با روش Transferable، به رشته اصلی تحویل میدهد.
رشته اصلی از طریق دسترسی فایل، بایتها را در فایل .sqlite کاربر مینویسد: createWritable، write، close. در نتیجه فایل روی دیسک یک پایگاه داده کامل و سازگار است.
تغییرهای پشت سر هم تجمیع میشوند. اگر نوشتن در حال انجام باشد، برنامه فقط ثبت میکند که بعد از پایان باید یک بار دیگر ذخیره کند. بنابراین برای هر دسته تغییر یک نوشتن انجام میشود، نه برای هر کلید فشردهشده.
۴. تشخیص فایل از روی محتوا
هنگام باز کردن، برنامه فایل را بهصورت بایت میخواند و امضای ابتدای آن، یعنی SQLite format 3، را بررسی میکند. ملاک محتواست، نه پسوند. ممکن است نام فایل به .json ختم شود اما محتوایش پایگاه داده باینری باشد. نسخههای قدیمی داده را بهصورت JSON ذخیره میکردند و همین ترکیب یک بار باعث شد پایگاه داده سالم «خالی» به نظر برسد. از آن زمان، امضای فایل معیار تشخیص است.
اگر فایل SQLite باشد، worker با sqlite3_deserialize آن را به پایگاه داده فعال تبدیل میکند. در حالت OPFS، تابع OpfsDb.importDb آن را به فایل پایدار وارد میکند. اگر JSON باشد، دادهها بهصورت یک نسخه کامل از وضعیت وارد میشوند. هر دو مسیر به همان پایگاه داده میرسند و در هر دو، مهاجرت نسخهها اجرا میشود.
۵. مسیر پردازش دادههای BVL
پایگاه رسمی مجوزهای BVL، اداره فدرال حمایت از مصرفکننده و ایمنی مواد غذایی آلمان، از طریق API عمومی در دسترس است. اما برای استفاده مستقیم در مرورگر مناسب نیست: مسیرهای متعدد، درخواستهای زیاد و نبود امکان استفاده آفلاین. برای همین، آمادهسازی از قبل در یک مسیر پردازش جداگانه انجام میشود؛ در مخزن عمومی pflanzenschutz-db:
هر دو روز یک بار، GitHub Actions دادههای تمام مسیرهای BVL را دریافت و اعتبارسنجی میکند. اطلاعات تکمیلی مانند امکان استفاده در کشاورزی ارگانیک، نام مواد مؤثره و عبارتهای هشدار خطر هم اضافه میشوند.
نتیجه یک فایل SQLite است که با Brotli و ZIP فشرده و از طریق GitHub Pages منتشر میشود. کنار آن یک فایل manifest قرار دارد که اندازه و هش SHA-256 هر فایل را مشخص میکند.
برنامه manifest را دریافت میکند و کمحجمترین قالبی را انتخاب میکند که مرورگر قادر به باز کردنش باشد. سپس پیشرفت دانلود را نشان میدهد و بایتها را به worker میفرستد.
worker فایل دانلودشده را بهصورت پایگاه داده موقت در حافظه باز میکند و جدولهایش را در یک تراکنش به پایگاه داده کاربر کپی میکند. ترتیب وابستگی جدولها رعایت میشود تا کلیدهای خارجی معتبر بمانند.
پس از آن، کل فهرست در فایل .sqlite خود کاربر قرار دارد و آفلاین قابل جستجوست. در لاگ داخل پایگاه داده ثبت میشود که کدام انتشار وارد شده است.
وضعیت در ۲۵ اکتبر ۲۰۲۶
مقدار
محصولات موجود در فهرست
2,165
موارد مصرف، به تفکیک محصول، گیاه و آفت
30,836
مواد مؤثره
482
حجم دانلود، Brotli / ZIP
6.8 MB / 12.5 MB
حجم پس از باز کردن فشردهسازی، SQLite
113 MB
۶. اجرای آفلاین و نصب برنامه
service worker هنگام نصب همه فایلهای ساخت را که نامشان هش دارد، از جمله ماژول WebAssembly، از قبل در کش ذخیره میکند. پس از آن برنامه بدون اینترنت باز میشود. در هر ساخت، نسخه کش جدیدی در service worker قرار میگیرد؛ وگرنه کاربران نصبشده روی کد قدیمی میمانند، چون مرورگر service worker با بایتهای یکسان را دوباره نصب نمیکند.
نسخه نصبشده دسکتاپ از طریق File Handling API برای فایلهای .sqlite، .db و .json ثبت میشود. با دوبار کلیک روی فایل، پایگاه داده مستقیم در برنامه باز میشود. دسترسی آخرین فایل در IndexedDB نگهداری میشود؛ بار بعد، برنامه فقط اجازه دسترسی میخواهد و همان فایل را باز میکند.
۷. سرعت و پایداری
بدون کپی بافرهای بزرگ. خروجی پایگاه داده و ورودی BVL با انتقال مالکیت بافر بین رشتهها جابهجا میشوند، نه با structured clone. برای داده ۱۰۰ مگابایتی، این تفاوت میتواند تعیین کند که رابط روان بماند یا قفل شود.
مهلت پاسخ متناسب با عملیات. برای فراخوانیهای معمول ۳۰ ثانیه و برای وارد کردن دادههای BVL تا هشت دقیقه در نظر گرفته شده است، چون مرورگر زمانسنج تبهای پسزمینه را کند میکند. اگر worker از کار بیفتد، همه درخواستهای معلق فوراً با خطا خاتمه مییابند و برای همیشه منتظر نمیمانند.
بارگذاری صفحهبهصفحه. سوابق، محصولات و نقاط GPS با نشانگر موقعیت یا cursor صفحهبندی میشوند. رابط فقط ردیفهای قابل مشاهده را نمایش میدهد.
رفع یک علت از دست رفتن داده. در حالت SQLite، worker سوابق را مستقیم مدیریت میکند و دیگر آنها را همراه نسخه وضعیت ارسال نمیکند. در غیر این صورت، ذخیره یک تنظیم میتوانست فهرست قدیمی را دوباره بنویسد و همه رکوردهای اضافهشده از زمان باز شدن فایل را پاک کند.
۸. محدودیتهای فعلی
اولویت با کامپیوتر است. دسترسی فایل با File System Access API فقط در مرورگرهای دسکتاپ مبتنی بر Chromium، مثل Chrome و Edge، وجود دارد. گوشیها این امکان را ندارند؛ چه Safari در iPhone و چه Chrome در Android. در این نسخه نمیتوان روی گوشی فایل باز کرد و پایگاه داده جدید فقط تا زمان بارگذاری دوباره صفحه باقی میماند. نسخه مناسب گوشی به روش ذخیره دیگری، مثل OPFS یا IndexedDB، نیاز دارد و هنوز ساخته نشده است.
OPFS به جداسازی نیاز دارد. ذخیره پایدار در worker با OPFS به cross-origin isolation و هدرهای COOP/COEP نیاز دارد که امکان تنظیمشان در GitHub Pages وجود ندارد. بنابراین در نسخه منتشرشده، پایگاه داده در حافظه worker اجرا میشود و نسخه اصلی دادهها همان فایل روی دیسک است.
بازنویسی کل فایل در هر ذخیره. فقط تغییرات نوشته نمیشوند؛ هر بار تمام فایل بازنویسی میشود. برای سوابق خود مجموعه مشکلی ایجاد نمیکند، اما با وارد کردن فهرست BVL، فایل از ۱۰۰ مگابایت بزرگتر میشود و زمان ذخیره محسوس خواهد بود. این روش فعلاً ساده نگه داشته شده است؛ گام بعدی میتواند نوشتن فقط صفحههای تغییریافته باشد.