दस्तावेज़
डेटाबेस
स्कोप्ड कनेक्शन स्वामित्व, टाइप की गई क्वेरी विफलताओं, माइग्रेशन बैकअप और स्थानीय दस्तावेज़ भंडारण के साथ SQLite दृढ़ता।
अंग्रेज़ी से स्वचालित रूप से अनुवादित। अंग्रेज़ी मूल देखें
दृढ़ता मॉडल
@cadcamfun/db के माध्यम से SQLite खोलता है bun:sqlite और इफ़ेक्ट के अंदर एक ड्रिज़ल डेटाबेस को उजागर करता है Database सेवा। साइडकार अपने एप्लिकेशन डेटाबेस को यहां संग्रहीत करता है <dataDir>/cadcamfun.db. कनेक्शन माइग्रेशन लागू करने से पहले राइट-फ़ॉरवर्ड लॉगिंग और विदेशी-कुंजी प्रवर्तन को सक्षम बनाता है।
डेटाबेस में परियोजनाओं और उनके संबंधित संसाधनों की कार्यशील प्रतिलिपि शामिल है। प्रोजेक्ट संस्करण-नियंत्रण ऑब्जेक्ट, पुल अनुरोध और वर्कफ़्लो रन भी स्थानीय रूप से संग्रहीत किए जाते हैं। AI प्रदाता क्रेडेंशियल एक अलग स्वामी-पठनीय JSON फ़ाइल का उपयोग करते हैं; एप्लिकेशन बियरर टोकन को प्राथमिकता के रूप में जारी रखने के बजाय लॉन्च के समय प्रदान किया जाता है।
स्कीमा और प्रवेश बिंदु
packages/db/src/schema.ts तालिकाओं, अनुक्रमणिका, संबंधों, डिफ़ॉल्ट और अनुमानित चयन/सम्मिलित प्रकारों को परिभाषित करता है। src/index.ts निर्यात Database, DatabaseError, बूंदाबांदी Db प्रकार, और स्कीमा नेमस्पेस। src/upgrade.ts माइग्रेशन प्लानिंग, बैकअप और ट्रांसेक्शनल एप्लिकेशन का मालिक है; src/migrate.ts कमांड-लाइन प्रवेश बिंदु है। जेनरेटेड एसक्यूएल और माइग्रेशन जर्नल लाइव इन packages/db/drizzle.
प्रत्येक कनेक्शन द्वारा खोला गया packages/db/src/index.ts sQLite को स्विच करता है journal_mode = WAL और चालू हो जाता है foreign_keys. डेटाबेस को बंद करना चलता है wal_checkpoint(TRUNCATE) इसलिए प्रक्रिया समाप्त होने पर मुख्य फ़ाइल पूरी हो जाती है। यदि चेकपॉइंट व्यस्त है या विफल रहता है, तो एक चेतावनी लॉग की जाती है और शटडाउन जारी रहता है।
संग्रहीत मूल्य
डोमेन पहचानकर्ता यूयूआईडी के लिए डिफ़ॉल्ट होते हैं जहां तालिका द्वारा कॉन्फ़िगर किया जाता है। ड्रिज़ल टाइमस्टैम्प कॉलम को जावास्क्रिप्ट तिथियों और JSON कॉलम को घोषित रिकॉर्ड प्रकारों में मैप करता है। HTTP रिपॉजिटरी दिनांकों को उनके वायर प्रतिनिधित्व में परिवर्तित करती है और डोमेन सीमा पर JSON को मान्य करती है। संग्रहीत JSON कॉलम पर टाइपस्क्रिप्ट प्रकार एनोटेशन स्वयं यह साबित नहीं करता है कि आयातित या पुराना डेटा वर्तमान डोमेन स्कीमा से मेल खाता है।
प्रोजेक्ट के पास चित्र, घटक और टूलपाथ होते हैं। टूलपाथ एक ड्राइंग, सामग्री, कटर और मशीन कॉन्फ़िगरेशन का संदर्भ दे सकते हैं; उनका data फ़ील्ड एक पोर्टेबल विनिर्माण दस्तावेज़ ले जा सकता है। अलग-अलग ड्राइंग, घटक और टूलपाथ संस्करण तालिकाएँ संपूर्ण-प्रोजेक्ट Git इतिहास के अलावा संसाधन संस्करण बनाए रखती हैं।
सेवा के माध्यम से पूछताछ करें
Database.layer फ़ाइल पथ स्वीकार करता है या :memory:, एक वैकल्पिक माइग्रेशन फ़ोल्डर, और एक वैकल्पिक बैकअप निर्देशिका। यह अपने इफ़ेक्ट स्कोप के लिए SQLite हैंडल प्राप्त करता है। कॉल करने वाले उपयोग करते हैं query(operation, run) सिंक्रोनस या एसिंक्रोनस ड्रिज़ल कार्य निष्पादित करने के लिए; विदेशी अपवाद बन जाते हैं DatabaseError ऑपरेशन के नाम और मूल कारण के साथ।
import { Database, schema } from "@cadcamfun/db"
import { Effect } from "effect"
const loadProjects = Effect.gen(function* () {
const database = yield* Database
return yield* database.query("projects.list", (db) =>
db.select().from(schema.projectTable).all())
}) रिपॉजिटरी के पास पहुंच नियम और पंक्ति व्याख्या है; साझा क्वेरी सहायक विफलता एट्रिब्यूशन प्रदान करता है। यह स्वचालित रूप से किसी क्वेरी को अधिकृत नहीं करता है या सेवा कॉल के मनमाने अनुक्रम के आसपास लेनदेन नहीं बनाता है।
व्यवहार को उन्नत करें
माइग्रेशन फ़ोल्डर के साथ एक परत खोलने पर माइग्रेशन फ़ाइलें पढ़ी जाती हैं और उनके नामों की तुलना की जाती है __drizzle_migrations. पुराने प्रारूप की एक पत्रिका को माइग्रेशन टाइमस्टैम्प और हैश का मिलान करके बैकफ़िल किया जाता है। एक बेजोड़ जर्नल माइग्रेशन पहचान का अनुमान लगाने के बजाय अपग्रेड को विफल कर देता है।
जब किसी मौजूदा ऑन-डिस्क डेटाबेस को अपग्रेड की आवश्यकता होती है, तो सेवा प्री-माइग्रेशन SQLite बैकअप का उपयोग करके बनाती है VACUUM INTO. यह एक आंशिक फ़ाइल को लिखता है, पूर्ण स्नैपशॉट का नाम बदलता है, और नवीनतम पांच मिलान प्री-माइग्रेशन बैकअप को बरकरार रखता है। डिफ़ॉल्ट बैकअप निर्देशिका है backups डेटाबेस के बगल में. नए और इन-मेमोरी डेटाबेस को इस प्री-अपग्रेड बैकअप की आवश्यकता नहीं है।
जर्नल परिवर्तन और लंबित SQL कथन एक तत्काल लेनदेन में चलते हैं। एक असफल माइग्रेशन लेन-देन को वापस ले जाता है और परत निर्माण को विफल कर देता है। डेटाबेस आरंभीकरण विफल होने पर एप्लिकेशन को तत्परता की घोषणा नहीं करनी चाहिए।
प्रवासन आदेश
bun run db:generate
bun run db:migrate बदलने के बाद माइग्रेशन उत्पन्न करें schema.ts, और जेनरेट किए गए SQL और जर्नल को एक साथ रखें। माइग्रेशन सीएलआई का उपयोग करता है DATABASE_URL जब आपूर्ति की जाती है, तो प्रारंभिक हटा देता है file: उपसर्ग, और अन्यथा खुलता है ./data/cadcamfun.db. रूट रैपर इस स्क्रिप्ट को चलाता है packages/db जैसी इसकी कार्यशील निर्देशिका है, वैसे ही इसका डिफ़ॉल्ट लक्ष्य है packages/db/data/cadcamfun.db. वेब स्टूडियो उपयोग करता है data/cadcamfun.db रिपोजिटरी रूट पर. पैकेज्ड साइडकार का उपयोग करता है CADCAMFUN_DATA_DIR. रखरखाव चलाते समय एक स्पष्ट डेटाबेस पथ का चयन करें ताकि ये प्रवेश बिंदु अनजाने में विभिन्न फ़ाइलों पर काम न करें।
माइग्रेशन फ़ोल्डर के बिना, Database.layer डेटाबेस खोलता है लेकिन एप्लिकेशन टेबल नहीं बनाता है। जिन परीक्षणों को संपूर्ण स्कीमा की आवश्यकता होती है, वे इन-मेमोरी डेटाबेस के साथ माइग्रेशन निर्देशिका प्रदान करते हैं।
डेटा डोमेन
- पहचान और सहयोग: उपयोगकर्ता, खाते, सत्र, प्रमाणक, सत्यापन टोकन, सदस्यता, संगठन, सदस्यता, निमंत्रण, वार्तालाप, संदेश, सूचनाएं और पुश सदस्यता।
- डिज़ाइन और निर्माण: परियोजनाएं, चित्र, घटक, उनके संस्करण और टिप्पणियाँ, सामग्री, उपकरण, मशीन कॉन्फ़िगरेशन, टूलपाथ और उत्पादन लागत रिकॉर्ड।
- आवेदन सेवाएँ: फ़ाइलें, लाइब्रेरी आइटम, प्लगइन रजिस्ट्री/कॉन्फ़िगरेशन, एपीआई कुंजियाँ, विश्लेषण और गतिविधि रिकॉर्ड, बाज़ार डेटा, एमसीपी कॉन्फ़िगरेशन और स्थानीय कुंजी-मूल्य प्रविष्टियाँ।
- परियोजना का इतिहास: Git रिपॉजिटरी, ऑब्जेक्ट और रेफरी, अनुरोध और समीक्षा खींचें, और वर्कफ़्लो चलता है।
एक तालिका की उपस्थिति एक दृढ़ता मॉडल स्थापित करती है। नेटवर्क एकीकरण और एप्लिकेशन सुविधाएँ अकेले टेबल अस्तित्व के बजाय उनके वास्तविक हैंडलर और सेवाओं पर निर्भर करती हैं।
स्थानीय कुंजी-मूल्य भंडारण
LocalKeyValue jSON-संगत एप्लिकेशन स्थिति बनी रहती है। साइडकार KvStore प्राप्त करने, सम्मिलित करने, हटाने और उपसर्ग-फ़िल्टर की गई सूची का समर्थन करता है। कुंजियों में गैर-व्हाट्सएप टेक्स्ट होना चाहिए और अधिकतम 512 अक्षर होने चाहिए। मान शून्य, स्ट्रिंग्स, बूलियन, परिमित संख्या, सरणियाँ और सादे वस्तुओं की अनुमति देते हैं; चक्र, फ़ंक्शन, गैर-परिमित संख्याएं और गैर-सादी वस्तुएं अस्वीकार कर दी जाती हैं।
प्रविष्टियों में एक अद्यतन टाइमस्टैम्प शामिल है। अपसर्ट उसी कुंजी के मान को प्रतिस्थापित करते हैं। उपसर्ग सूची कुंजी और मेमोरी में फ़िल्टर के आधार पर क्रमबद्ध होती है। प्राथमिकताओं और सहायक संदर्भ के लिए इस स्टोर का उपयोग करें; क्रेडेंशियल उनकी समर्पित क्रेडेंशियल सेवा से संबंधित हैं।
शटडाउन और पुनर्प्राप्ति
डेटाबेस स्कोप फ़ाइनलाइज़र अनुरोध PRAGMA wal_checkpoint(TRUNCATE) हैंडल बंद करने से पहले. एक व्यस्त चेकपॉइंट या बंद विफलता को चेतावनी के रूप में लॉग किया जाता है ताकि शेष फ़ाइनलाइज़र चल सकें। व्यक्तिगत HTTP हैंडलर के बजाय कनेक्शन स्वामी, हैंडल को बंद कर देता है।
लगातार मैन्युअल बैकअप के लिए, एप्लिकेशन को उसकी डेटा निर्देशिका की प्रतिलिपि बनाने से पहले साफ़-साफ़ बंद कर दें, या उसके चलने के दौरान SQLite की बैकअप सुविधाओं का उपयोग करें। एक लाइव डेटाबेस की वाल फ़ाइल में स्थिति हो सकती है। प्री-माइग्रेशन बैकअप का निरीक्षण करने के लिए, एक कॉपी पर काम करें और पुनर्प्राप्ति की पुष्टि होने तक मूल डेटाबेस और बैकअप को सुरक्षित रखें।
भंडार जिम्मेदारियाँ
इस पैकेज में SQLite कनेक्शन निर्माण और माइग्रेशन तर्क रखें। साइडकार रिपॉजिटरी प्रदान की गई डेटाबेस सेवा का उपयोग करते हैं और भंडारण विफलताओं को उनके संसाधन की HTTP त्रुटियों में मैप करते हैं। ज्यामिति गणना को मूल में रखें और क्रेडेंशियल या टोकन सेवाओं में रहस्य रखें। डेटाबेस बैकअप में प्रोजेक्ट और खाता डेटा होता है और सक्रिय डेटा निर्देशिका के समान पहुंच नियंत्रण की आवश्यकता होती है।
किसी डेटाबेस को बदले बिना उसका निरीक्षण करें
क्लीन शटडाउन के बाद, स्पष्ट डेटाबेस पथ के विरुद्ध SQLite CLI का उपयोग करें। पथ गलत होने पर रीड-ओनली मोड गलती से एक नई खाली फ़ाइल बनाने से बचता है। ये जाँच खाते या क्रेडेंशियल पंक्तियों को उजागर किए बिना संरचना और स्थिरता का निरीक्षण करती हैं।
sqlite3 -readonly /absolute/path/cadcamfun.db 'PRAGMA quick_check;'
sqlite3 -readonly /absolute/path/cadcamfun.db 'PRAGMA foreign_key_check;'
sqlite3 -readonly /absolute/path/cadcamfun.db "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;"
sqlite3 -readonly /absolute/path/cadcamfun.db 'SELECT name, applied_at FROM __drizzle_migrations ORDER BY id;' quick_check सामान्यतः रिपोर्ट करता है ok; foreign_key_check केवल उल्लंघनों के लिए पंक्तियाँ लौटाता है। के बिना एक पत्रिका name/applied_at कॉलम एक पुराना प्रारूप है, जिसे एप्लिकेशन अपग्रेड कोड को अंतिम क्वेरी का उपयोग करने से पहले मिलान करना होगा। मरम्मत का प्रयास करने से पहले पथ और माइग्रेशन पहचान की जाँच करें।
एप्लिकेशन अपने स्वयं के कनेक्शन पर विदेशी-कुंजी प्रवर्तन सेट करता है। एक अलग से खोले गए रखरखाव कनेक्शन को अधिकृत लेखन करने से पहले इसे स्पष्ट रूप से सक्षम करना होगा; PRAGMA कनेक्शन-विशिष्ट है.
स्रोत: packages/db/src/index.ts, upgrade.ts, और database.test.ts.
कोड में डिस्पोजेबल डेटाबेस का उपयोग करें
एक पूर्ण इन-मेमोरी सेवा दायरा रिपॉजिटरी उदाहरणों और पृथक निदान के लिए उपयोगी है। स्कोप कनेक्शन का मालिक है और प्रभाव सेवा को पढ़ने से पहले चेक-इन माइग्रेशन लागू करता है।
import { Database, schema } from "@cadcamfun/db"
import { Effect } from "effect"
const migrationsFolder = new URL("../../packages/db/drizzle", import.meta.url).pathname
const program = Effect.gen(function* () {
const database = yield* Database
return yield* database.query("diagnostic.projects", (db) =>
db.select({ id: schema.projectTable.id }).from(schema.projectTable).all())
}).pipe(Effect.provide(Database.layer({ path: ":memory:", migrationsFolder })))
console.log(await Effect.runPromise(program)) // [] इस स्क्रिप्ट को इस रूप में सहेजें apps/sidecar/diagnostic.ts और भाग खड़ा हुआ bun apps/sidecar/diagnostic.ts रिपोजिटरी रूट से. यह पैकेज डेटाबेस और प्रभाव निर्भरता की आपूर्ति करता है, और माइग्रेशन URL उस फ़ाइल से हल होता है। एक गुम या गलत माइग्रेशन निर्देशिका एक खाली एप्लिकेशन स्कीमा के बराबर नहीं है। बूंदाबांदी query कॉलबैक एक समकालिक क्वेरी चला सकता है या कोई वादा लौटा सकता है; सहायक आपूर्ति किए गए ऑपरेशन लेबल के अंतर्गत विफलताओं को लपेटता है।
स्रोत: packages/db/src/database.test.ts और index.ts.
भंडारण विफलताओं का निदान करें
- ऐसी कोई तालिका नहीं: सटीक डेटाबेस फ़ाइल और माइग्रेशन फ़ोल्डर की पुष्टि करें। सेवा द्वारा माइग्रेशन के बिना खोलने की अनुमति है, लेकिन एप्लिकेशन तालिकाओं को क्वेरी करना विफल हो जाता है।
- विदेशी-कुंजी बाधा विफल: संदर्भित स्वामी/परियोजना/संसाधन का निरीक्षण करें। विलोपन प्रतिबंध स्कीमा-विशिष्ट हैं: किसी स्वामित्व वाले प्रोजेक्ट वाले उपयोगकर्ता को हटाना प्रतिबंधित है, जबकि सत्र पंक्तियाँ तब कैस्केड होती हैं जब उनका उपयोगकर्ता हटा दिया जाता है।
- अपग्रेड के दौरान बैकअप विफल: खाली स्थान की जांच करें और डेटाबेस और बैकअप निर्देशिकाओं में पहुंच लिखें। बैकअप विफलता से माइग्रेशन रुक जाता है; इसे बायपास करने के लिए मूल डेटाबेस को न हटाएं।
- लीगेसी माइग्रेशन जर्नल स्थानीय माइग्रेशन से मेल नहीं खाता: डेटाबेस को सुरक्षित रखें और मिलान माइग्रेशन सेट को पुनर्प्राप्त करें। जर्नल पंक्तियों का नाम बदलने या हटाने से असंगत अपग्रेड इतिहास छिप जाएगा।
- चेकपॉइंट शटडाउन पर व्यस्त: केवल डेटाबेस फ़ाइल की प्रतिलिपि बनाने से पहले अन्य खुले कनेक्शनों का निरीक्षण करें। एक साफ़ चेकपॉइंट या लगातार SQLite बैकअप पूरा होने तक WAL/SHM भाई-बहनों को बनाए रखें।
माइग्रेशन बैकअप पांच-फ़ाइल अवधारण नीति के साथ प्री-अपग्रेड पुनर्प्राप्ति बिंदु हैं, बाद के संपादनों का निरंतर बैकअप नहीं। इंस्टॉलेशन की पुनर्प्राप्ति आवश्यकताओं के अनुसार संपूर्ण डेटा निर्देशिका का अलग से बैकअप लें।
स्रोत: packages/db/src/index.ts, upgrade.ts, schema.ts, और database.test.ts.
प्रवासन इतिहास
चेक-इन माइग्रेशन फ़ोल्डर क्रम में लागू किए जाते हैं। प्रत्येक फ़ोल्डर में एक होता है migration.sql और बूंदा-बांदी-किट snapshot.json अगले अंतर की गणना करने के लिए उपयोग किया जाता है। जर्नल पंक्ति फ़ोल्डर का नाम, उसका हैश, फ़ोल्डर टाइमस्टैम्प को मिलीसेकंड में संग्रहीत करती है (created_at), और आईएसओ समय इसे लागू किया गया था (applied_at).
| फ़ोल्डर | आकार | यह क्या बनाता है |
|---|---|---|
20261004223029_careful_monster_badoon | 771 पंक्तियाँ | बेसलाइन स्कीमा को पुराने प्रिज्मा मॉडल से परिवर्तित किया गया: पहचान, संगठन, परियोजनाएं, चित्र, घटक, टूलपाथ, लाइब्रेरी, लागत, बाज़ार, प्लगइन्स और एमसीपी कॉन्फ़िगरेशन। तालिका और स्तंभ नाम अपरिवर्तित हैं इसलिए पुराने हैं dev.db डेटा पठनीय रहता है. |
20261008030518_redundant_dagger | 73 पंक्तियाँ | परियोजना का इतिहास: GitRepo, GitObject, GitRef, PullRequest, PullRequestReview, WorkflowRun. |
20261009012351_moaning_loki | 28 पंक्तियाँ | ज्यामिति कर्नेल रिकॉर्ड: MeshAsset और CadOperationLog. |
20261009171602_brown_mad_thinker | 5 पंक्तियाँ | LocalKeyValue (key पाठ प्राथमिक कुंजी, value पाठ शून्य नहीं है, updatedAt पूर्णांक शून्य नहीं)। |
फ़ोल्डर नाम ड्रिज़ल-किट से आते हैं: एक यूटीसी टाइमस्टैम्प जिसके बाद एक यादृच्छिक नाम आता है। एक बार किसी फ़ोल्डर को कहीं भी लागू करने के बाद उसका नाम न बदलें या उसे संपादित न करें; अपग्रेड प्लानर लागू माइग्रेशन को नाम और पुराने जर्नल के लिए टाइमस्टैम्प और हैश के आधार पर पहचानता है।
निर्णय प्रवाह को उन्नत करें
| परिस्थिति | बैकअप | परिणाम |
|---|---|---|
| नई फ़ाइल, माइग्रेशन फ़ोल्डर दिया गया | नहीं (फ़ाइल खुलने से पहले मौजूद नहीं थी) | सभी माइग्रेशन एक लेनदेन में लागू होते हैं |
| मौजूदा फ़ाइल, जर्नल अद्यतन | नहीं | वैसे ही खोला गया; needed झूठ है |
| मौजूदा फ़ाइल, लंबित माइग्रेशन | हाँ, किसी भी बदलाव से पहले | लंबित माइग्रेशन लागू; जर्नल पंक्तियाँ सम्मिलित की गईं applied_at |
मौजूदा फ़ाइल, जर्नल बिना name स्तंभ | हाँ | कॉलम name और applied_at जोड़ा गया, पंक्तियाँ बैकफ़िल की गईं, फिर लंबित माइग्रेशन लागू किए गए |
| लीगेसी पंक्ति किसी स्थानीय माइग्रेशन से मेल नहीं खाती | कोई बैकअप नहीं लिया जाता: योजना पहले विफल हो जाती है | DatabaseError ऑपरेशन के साथ migrate: "विरासत प्रवासन जर्नल स्थानीय प्रवासन से मेल नहीं खाता" |
:memory: | कभी नहीं | यदि कोई फ़ोल्डर दिया गया है तो माइग्रेशन लागू होता है |
| कोई माइग्रेशन फ़ोल्डर नहीं | कभी नहीं | तालिकाएँ बनाए बिना खोला गया |
बैकफ़िल मिलान इस तरह काम करता है: एक विरासत पंक्ति created_at इसे पूरे सेकंड में छोटा कर दिया गया है और प्रत्येक माइग्रेशन के फ़ोल्डर टाइमस्टैम्प के साथ तुलना की गई है। यदि बिल्कुल एक माइग्रेशन मेल खाता है, तो इसका उपयोग किया जाता है। अन्यथा हैश बंधन को तोड़ देता है, और अंतिम उपाय के रूप में उसी हैश के साथ किसी भी माइग्रेशन का उपयोग किया जाता है।
बैकअप फ़ाइल शरीर रचना
backups/cadcamfun-20261015-034512.123-6f1c2d4e-8a90-4b7c-9e21-3f5a6b7c8d9e-pre-migrate.db
└ prefix ┘ └ UTC timestamp ┘ └ random UUID ┘ - उपसर्ग बिना डेटाबेस फ़ाइल नाम है
.db, उसके बाद एक पानी का छींटा। - टाइमस्टैम्प मिलीसेकंड परिशुद्धता के साथ यूटीसी है। यदि नवीनतम मौजूदा बैकअप में समान या बाद वाला टाइमस्टैम्प है, तो नया टाइमस्टैम्प इसके बाद 1 एमएस सेट किया गया है, इसलिए शाब्दिक क्रम हमेशा निर्माण क्रम के बराबर होता है।
- स्नैपशॉट को लिखा गया है
<name>.partialसाथVACUUM INTO, फिर नाम बदल दिया गया। एक दुर्घटना अधिकतम एक छोड़ देती है.partialफ़ाइल, जिसे a में हटा दिया गया हैfinallyअवरोध पैदा करना। - सफल बैकअप के बाद, सटीक पैटर्न से मेल खाने वाली केवल पांच नवीनतम फ़ाइलें रखी जाती हैं। जिन फ़ाइलों को आप अन्य नामों के तहत निर्देशिका में कॉपी करते हैं वे कभी भी हटाई नहीं जाती हैं।
VACUUM INTOबिना किसी वाल सिबलिंग के एक कॉम्पैक्ट, स्व-निहित डेटाबेस तैयार करता है, इसलिए बैकअप सीधे खोला जा सकता है।
DATA="/absolute/path/to/data"
cp "$DATA/cadcamfun.db" "$DATA/cadcamfun.db.broken" # keep the failed state
rm -f "$DATA/cadcamfun.db-wal" "$DATA/cadcamfun.db-shm"
cp "$DATA/backups/cadcamfun-<timestamp>-<uuid>-pre-migrate.db" "$DATA/cadcamfun.db"
sqlite3 -readonly "$DATA/cadcamfun.db" 'PRAGMA quick_check;' # expect: ok रोलबैक स्कीमा और डेटा को पुनर्स्थापित किया जा रहा है
पुनर्स्थापित बैकअप अपग्रेड से ठीक पहले की स्थिति है। उस अपग्रेड के बाद किए गए संपादन इसमें नहीं हैं, और अगले लॉन्च में फिर से उसी माइग्रेशन का प्रयास किया जाएगा। पुनरारंभ करने से पहले विफलता का कारण ठीक करें।
कोर टेबल आकार
ये वे तालिकाएँ हैं जिन्हें डेस्कटॉप संपादक, इतिहास और कर्नेल सबसे अधिक बार पढ़ते हैं। कॉलम नाम SQL नाम हैं; बूंदा बांदी उन्हें उन्हीं चाबियों के नीचे उजागर करती है।
| मेज़ | कॉलम |
|---|---|
Project | id, name, description, createdAt, updatedAt, ownerId, organizationId, isPublic |
Drawing | id, name, description, data, thumbnail, createdAt, updatedAt, projectId |
Component | id, name, description, data, thumbnail, type, isPublic, createdAt, updatedAt, projectId |
Toolpath | id, name, description, data, type, operationType, gcode, thumbnail, isPublic, projectId, createdAt, updatedAt, createdBy, drawingId, materialId, toolId, machineConfigId |
GitRepo | projectId, head, remote, createdAt |
GitObject | projectId, oid, type, body |
GitRef | projectId, name, oid |
PullRequest | id, projectId, number, title, body, head, base, state, authorId, authorKind, mergeCommit, remoteNumber, createdAt, updatedAt |
WorkflowRun | id, projectId, workflow, event, ref, sha, status, events, startedAt, finishedAt |
MeshAsset | id, projectId, kind, inputs, stats, mesh, createdAt |
CadOperationLog | id, projectId, operation, meshAssetId, outcome, durationMs, inputs, error, traceId, spanId, createdAt |
LocalKeyValue | key, value, updatedAt |
किसी प्रोजेक्ट को हटाने से उसके चित्र, घटक, टूलपाथ, इतिहास ऑब्जेक्ट और रेफरी, पुल अनुरोध, वर्कफ़्लो रन, मेष संपत्ति और ऑपरेशन लॉग हटा दिए जाते हैं। संस्करण और टिप्पणी पंक्तियाँ अपने मूल संसाधन से कैस्केड होती हैं। ए CadOperationLog पंक्ति अपनी जाली संपत्ति के विलोपन से बच जाती है meshAssetId शून्य पर सेट करें. सामग्री, उपकरण और मशीन कॉन्फ़िगरेशन के टूलपाथ लिंक में कोई कैस्केड नहीं होता है, इसलिए किसी संदर्भित सामग्री को तब हटाया नहीं जा सकता जब टूलपाथ उस पर इंगित करता है।
पूर्ण तालिका सूची
स्कीमा 60 तालिकाओं को परिभाषित करती है। नीचे दी गई सूची ड्रिज़ल तालिका परिभाषाओं से तैयार की गई थी: एसक्यूएल नाम, निर्यातित स्थिरांक, कॉलम गिनती, घोषित इंडेक्स की संख्या, और उनके डिलीट नियम के साथ विदेशी कुंजी। "कोई कार्रवाई नहीं" SQLite का डिफ़ॉल्ट है: संदर्भ पंक्तियाँ मौजूद होने पर डिलीट विफल हो जाता है (एप्लिकेशन कनेक्शन पर विदेशी कुंजियाँ लागू होती हैं)।
| एसक्यूएल टेबल | निर्यात | कॉलम | आईडीएक्स | विदेशी कुंजियाँ |
|---|---|---|---|---|
Account | accountTable | 13 | 1 | userId → उपयोगकर्ता (कैस्केड) |
ActivityLog | activityLogTable | 7 | 0 | userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
AIAnalysisLog | aIAnalysisLogTable | 7 | 0 | userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
ApiKey | apiKeyTable | 7 | 1 | userId → उपयोगकर्ता (कैस्केड) |
authenticators | authenticatorTable | 8 | 0 | userId → उपयोगकर्ता (कैस्केड) |
CadOperationLog | cadOperationLogTable | 11 | 1 | projectId → प्रोजेक्ट (कैस्केड)meshAssetId → मेशएसेट (सेट शून्य) |
Component | componentTable | 10 | 0 | projectId → प्रोजेक्ट (कैस्केड) |
ComponentComment | componentCommentTable | 6 | 0 | componentId → घटक (कैस्केड)userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
ComponentVersion | componentVersionTable | 6 | 0 | componentId → घटक (कैस्केड)userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
Conversation | conversationTable | 6 | 0 | organizationId → संगठन (कैस्केड) |
ConversationParticipant | conversationParticipantTable | 5 | 1 | userId → उपयोगकर्ता (कैस्केड)conversationId → बातचीत (कैस्केड) |
CostSettings | costSettingsTable | 11 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
Drawing | drawingTable | 8 | 0 | projectId → प्रोजेक्ट (कैस्केड) |
DrawingVersion | drawingVersionTable | 5 | 0 | drawingId → ड्राइंग (कैस्केड) |
FileUpload | fileUploadTable | 12 | 0 | — |
GitObject | gitObjectTable | 4 | 1 | projectId → प्रोजेक्ट (कैस्केड) |
GitRef | gitRefTable | 3 | 1 | projectId → प्रोजेक्ट (कैस्केड) |
GitRepo | gitRepoTable | 4 | 0 | projectId → प्रोजेक्ट (कैस्केड) |
LibraryItem | libraryItemTable | 14 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
LocalKeyValue | localKeyValueTable | 3 | 0 | — |
MachineConfig | machineConfigTable | 9 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
MarketplaceCategory | marketplaceCategoryTable | 10 | 1 | parentId → मार्केटप्लेसश्रेणी (कोई कार्रवाई नहीं) |
MarketplaceCollection | marketplaceCollectionTable | 10 | 1 | sellerId → मार्केटप्लेस विक्रेता (कोई कार्रवाई नहीं) |
MarketplaceCollectionItem | marketplaceCollectionItemTable | 5 | 1 | collectionId → मार्केटप्लेसकलेक्शन (कैस्केड)itemId → मार्केटप्लेसआइटम (कैस्केड) |
MarketplaceItem | marketplaceItemTable | 30 | 5 | sellerId → मार्केटप्लेस विक्रेता (कोई कार्रवाई नहीं) |
MarketplaceOrder | marketplaceOrderTable | 23 | 4 | buyerId → उपयोगकर्ता (कोई कार्रवाई नहीं)sellerId → मार्केटप्लेस विक्रेता (कोई कार्रवाई नहीं)itemId → मार्केटप्लेसआइटम (कोई कार्रवाई नहीं) |
MarketplacePayout | marketplacePayoutTable | 12 | 1 | sellerId → मार्केटप्लेस विक्रेता (कोई कार्रवाई नहीं) |
MarketplaceReview | marketplaceReviewTable | 12 | 2 | itemId → मार्केटप्लेसआइटम (कोई कार्रवाई नहीं)buyerId → उपयोगकर्ता (कोई कार्रवाई नहीं)orderId → मार्केटप्लेसऑर्डर (कोई कार्रवाई नहीं) |
MarketplaceSeller | marketplaceSellerTable | 19 | 0 | userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
MarketplaceWishlist | marketplaceWishlistTable | 4 | 1 | userId → उपयोगकर्ता (कैस्केड)itemId → मार्केटप्लेसआइटम (कैस्केड) |
Material | materialTable | 9 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
MaterialCost | materialCostTable | 10 | 0 | materialId → सामग्री (कैस्केड)ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
MCPServerConfig | mCPServerConfigTable | 11 | 1 | — |
MeshAsset | meshAssetTable | 7 | 1 | projectId → प्रोजेक्ट (कैस्केड) |
Message | messageTable | 8 | 1 | senderId → उपयोगकर्ता (कैस्केड)conversationId → बातचीत (कैस्केड)fileId → फ़ाइल अपलोड करें (शून्य सेट करें) |
Notification | notificationTable | 12 | 0 | userId → उपयोगकर्ता (कैस्केड)organizationId → संगठन (कैस्केड)projectId → प्रोजेक्ट (कैस्केड)componentId → घटक (कैस्केड)messageId → संदेश (कैस्केड) |
OperationCost | operationCostTable | 10 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
Organization | organizationTable | 5 | 0 | — |
OrganizationInvitation | organizationInvitationTable | 7 | 0 | organizationId → संगठन (कैस्केड) |
passkey | passkeyTable | 11 | 0 | userId → उपयोगकर्ता (कैस्केड) |
PluginConfiguration | pluginConfigurationTable | 2 | 0 | pluginId → प्लगइनरजिस्ट्रीएंट्री (कैस्केड) |
PluginRegistryEntry | pluginRegistryEntryTable | 9 | 0 | — |
ProductionCostEstimate | productionCostEstimateTable | 17 | 0 | toolpathId → टूलपाथ (कैस्केड)operationCostId → ऑपरेशनकॉस्ट (कोई कार्रवाई नहीं)ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
Project | projectTable | 8 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
PullRequest | pullRequestTable | 14 | 1 | projectId → प्रोजेक्ट (कैस्केड)authorId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
PullRequestReview | pullRequestReviewTable | 8 | 1 | pullRequestId → पुल रिक्वेस्ट (कैस्केड)reviewerId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
PushSubscription | pushSubscriptionTable | 6 | 0 | userId → उपयोगकर्ता (कैस्केड) |
Session | sessionTable | 8 | 0 | userId → उपयोगकर्ता (कैस्केड) |
Subscription | subscriptionTable | 24 | 3 | referenceId → उपयोगकर्ता (कैस्केड) |
Token | tokenTable | 8 | 2 | userId → उपयोगकर्ता (कैस्केड) |
Tool | toolTable | 17 | 0 | ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
Toolpath | toolpathTable | 17 | 0 | projectId → प्रोजेक्ट (कैस्केड)createdBy → उपयोगकर्ता (कोई कार्रवाई नहीं)drawingId → आरेखण (कोई क्रिया नहीं)materialId → सामग्री (कोई कार्रवाई नहीं)toolId → टूल (कोई कार्रवाई नहीं)machineConfigId → मशीन कॉन्फिग (कोई कार्रवाई नहीं) |
ToolpathComment | toolpathCommentTable | 6 | 0 | toolpathId → टूलपाथ (कैस्केड)userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
ToolpathVersion | toolpathVersionTable | 7 | 0 | toolpathId → टूलपाथ (कैस्केड)userId → उपयोगकर्ता (कोई कार्रवाई नहीं) |
ToolWearCost | toolWearCostTable | 10 | 0 | toolId → टूल (कैस्केड)ownerId → उपयोगकर्ता (कोई कार्रवाई नहीं)organizationId → संगठन (कोई कार्रवाई नहीं) |
twoFactor | twoFactorTable | 4 | 0 | userId → उपयोगकर्ता (कैस्केड) |
User | userTable | 17 | 0 | — |
UserOrganization | userOrganizationTable | 5 | 1 | userId → उपयोगकर्ता (कैस्केड)organizationId → संगठन (कैस्केड) |
verification_tokens | verificationTokenTable | 3 | 1 | — |
WorkflowRun | workflowRunTable | 10 | 1 | projectId → प्रोजेक्ट (कैस्केड) |
सुरक्षित रूप से लिखना
- ड्रिज़ल लेनदेन में बहु-कथन परिवर्तनों को एक के अंदर लपेटें
queryपुकारना:database.query("op", (db) => db.transaction((tx) => ...)). अलगqueryकॉल अलग-अलग लेनदेन हैं। - प्रत्येक क्वेरी को एक स्थिर, बिंदीदार ऑपरेशन नाम दें (
projects.list,toolpaths.update). यह एकमात्र प्रसंग हैDatabaseErrorकारण से परे है, और यह लॉग में दिखाई देता है। - के साथ आईडी जनरेट करें
newId()(एक यूयूआईडी) या कॉलम को डिफ़ॉल्ट रूप से ऐसा करने दें; नामों से आईडी न बनाएं. - JSON कॉलम पढ़ते समय उन्हें मान्य करें। घोषित टाइपस्क्रिप्ट प्रकार की जाँच SQLite द्वारा नहीं की जाती है।
- उपयोग
LocalKeyValueपंक्तियों को सीधे लिखने के बजाय साइडकार कुंजी-मूल्य सेवा के माध्यम से, इसलिए कुंजी और मूल्य सत्यापन लागू किया जाता है।
import { Database, schema } from "@cadcamfun/db"
import { eq } from "drizzle-orm"
import { Effect } from "effect"
const renameProject = (id: string, name: string) => Effect.gen(function* () {
const database = yield* Database
return yield* database.query("projects.rename", (db) =>
db.transaction((tx) => {
const updated = tx.update(schema.projectTable)
.set({ name, updatedAt: new Date() })
.where(eq(schema.projectTable.id, id))
.returning().all()
if (updated.length === 0) throw new Error(`project ${id} not found`)
return updated[0]
}))
}) स्पष्ट आईडी के साथ पंक्तियाँ बनाने के लिए, उपयोग करें schema.newId(); @cadcamfun/db स्कीमा मॉड्यूल को पुनः निर्यात करता है schema नेमस्पेस, शीर्ष-स्तरीय नामों के रूप में नहीं।