طرحواره
.erd.json قالب سند ویرایشگر است. اگر لازم است سندی را بیرون از ویرایشگر تولید یا اعتبارسنجی کنید یا آن را مهاجرت دهید، این صفحه را بخوانید.
این صفحه شکل ذخیرهسازی را توصیف میکند، یعنی سند را به همان صورتی که یک فایل در خود دارد، که هر نسخه از 4.0.0 به بعد آن را مینویسد. همان چیزی است که editor.value برمیگرداند، همان چیزی که صادر کردن JSON مینویسد و تنها شکلی که JSON Schema منتشرشده میپذیرد. version آن '3.0.0' است، مانند هر فایل v3 که نسخهای قدیمیتر ذخیره کرده، بنابراین version فایل قدیمیتر را از فایل جدیدتر تشخیص نمیدهد. setInitialValue()، setter خاصیت value و setSchemaJSON() آن، هر فایلی که نسخهای قدیمیتر ذخیره کرده و یک سند v2 با قالب .vuerd را میخوانند. پیش از نسخهٔ 4.0.0، value کل سند را همانطور که ویرایشگر در خود داشت برمیگرداند، بنابراین فایلی که آن زمان ذخیره شده چیزهای بیشتری در خود دارد (شکل ذخیرهسازی را ببینید).
runtimeValue یک ویرایشگر شکل سریالشدهٔ دیگری است که این صفحه آن را توصیف نمیکند. برای مقداردهی اولیهٔ ویرایشگر یا رونوشت دیگری به کار میرود و یک اتاق Yjs آن را در تصویر لحظهای خود ذخیره میکند؛ هرگز جایش در فایل نیست و JSON Schema هر مقداری از آن را که موجودیتی در خود داشته باشد رد میکند.
شکل ذخیرهسازی
شکل ذخیرهسازی فقط موجودیتهای حذفنشده را در خود دارد: هر جدولی که در doc.tableIds فهرست شده، ستونهایی که آن جدولها فهرست کردهاند، رابطههای میان دو جدول باقیمانده، شاخصهای جدولهای باقیمانده همراه با ستونهای شاخصی که جدول هنوز ستونشان را فهرست کرده است، یادداشتها و گروههای جدول فهرستشده و از نسخهٔ 4.2.0، واژهها، اصطلاحات و دامنههای برگههای واژهنامه که افزون بر شناسهٔ خود مقداری دارند. چیزی را که ویرایشگر هنگام بارگذاری به دست میآورد یا فقط تا وقتی باز است نگه میدارد در خود ندارد: نه ترتیب لایهها، نه عرضهای اندازهگیریشده یا نشانههای کلید، و نه اینکه رابطه شناسا است یا نه، انتهای والد آن چگونه رسم میشود یا کجا به جدولهایش میرسد. هر بارگذاری اینها را دوباره از آنچه فایل در خود دارد به دست میآورد.
هر مجموعه، بهجز واژهنامهها، با شناسهها و به ترتیب واحدهای کد کلیدگذاری میشود و در آن ستونها ابتدا بر اساس tableId و ستونهای شاخص ابتدا بر اساس indexId گروهبندی میشوند. از نسخهٔ 4.2.0، wordEntities، termEntities و domainEntities به همین ترتیب پس از همهٔ مجموعههای دیگر میآیند و هر کدام بهصورت یک سرآیند و ردیفها، هر ردیف در یک خط، نوشته میشود (ردیفهای واژهنامه را ببینید). هر موجودیت فیلدهایش را به ترتیبی ثابت مینویسد و متن با دو فاصله تورفتگی دارد و با یک نویسهٔ خط جدید پایان مییابد. بنابراین سندی یکسان همیشه به همان بایتها نوشته میشود، هر ویرایش فقط بخشی را که به آن دست میزند تغییر میدهد و فایلی که روی رایانهای با قلمهای دیگر ذخیره شده با همان value دوباره باز میشود.
VS Code، Obsidian و پلاگین JetBrains فقط وقتی فایل را مینویسند که ویرایشی value را تغییر دهد، بنابراین فایلی که نسخهای قدیمیتر ذخیره کرده تا نخستین ویرایشش شکل قدیمی خود را حفظ میکند.
از نسخهٔ 4.2.0، شکل ذخیرهسازی آنچه را چیزی در خود ندارد نیز کنار میگذارد: هر فیلد متنی که یک موجودیت یا ui آن بهصورت '' نگه میدارد (name، comment و ui.color جدول، name، comment، dataType و default ستون، name شاخص، value و ui.color یادداشت، name و color گروه جدول)، هر فهرست doc و هر مجموعهای که هیچ مدخلی ندارد، و خود collections وقتی همهٔ مجموعهها خالی باشند. متنی که فقط از فاصله تشکیل شده باشد همانطور که هست نوشته میشود، بهجز نام منطقی که در این صورت کنار گذاشته میشود، و واژه، اصطلاح یا دامنهای که همهٔ مقادیرش بهجز شناسه خالی یا فقط فاصله باشند، که بهطور کامل کنار گذاشته میشود. هر شناسه، هر فهرست درون یک موجودیت و هر عدد، از جمله 0، همچنان نوشته میشود. doc همیشه نوشته میشود، بنابراین فایل یک سند جدید $schema، version، تنظیمات آن و "doc": {} را در خود دارد.
هنگام تجزیه، فیلد متنی ناموجود '' و مجموعهٔ ناموجود خالی خوانده میشود، همانطور که همهٔ نسخههای v3 این کار را میکنند، و شکل ذخیرهسازی یک فهرست doc را فقط تا وقتی مجموعهٔ آن چیزی در خود ندارد کنار میگذارد (Doc را ببینید). بنابراین ویرایشگرهای پیش از نسخهٔ 4.2.0 نیز این فایلها را باز میکنند و برنامهای که خودش فایل را میخواند باید آنچه را ناموجود است به همین شیوه بخواند. فایلی که نسخهای قدیمیتر ذخیره کرده، پس از ذخیرهٔ بعدیاش بدون متنها، فهرستها و مجموعههای خالیاش نوشته میشود، که تغییری یکباره است، و از آن پس بایت به بایت یکسان ذخیره میشود.
شکل ذخیرهسازی هر تنظیم قفلشده را با مقدار قفلشدهاش (lockSettings را ببینید)، settings.ddlScripts را فقط تا وقتی اسکریپتی متن دارد و groupId جدول را فقط تا وقتی مینویسد که به گروه جدولی اشاره کند که فایل آن را مینویسد. از نسخهٔ 4.2.0، settings.nameViewMode را نیز فقط تا وقتی مقداری که مینویسد 'physical' نیست، settings.columnOrder را هر جا ممکن باشد با هفت مدخل (Settings را ببینید) و nameDerived جدول را فقط تا وقتی true است مینویسد.
همچنین doc.tableGroupIds و tableGroupEntities را فقط تا وقتی گروه جدولی وجود دارد، logicalName را فقط تا وقتی متنی غیر از فاصله دارد، domainId ستون را فقط تا وقتی به دامنهای اشاره میکند که فایل آن را مینویسد، و هر واژهنامه را فقط تا وقتی ردیفی دارد که فایل آن را مینویسد، مینویسد.
فایلی که پیش از نسخهٔ 4.0.0 ذخیره شده کل سند را همانطور که ویرایشگر آن زمان در خود داشت دربر دارد، با موجودیتهای حذفشدهاش و آنچه هر بارگذاری به دست میآورد. بارگذاری آن را میخواند، جایگاه هر جدول و یادداشت را در پشته نگه میدارد (Doc را ببینید) و بقیه را دوباره به دست میآورد، و ذخیرهٔ بعدی فقط شکل ذخیرهسازی را مینویسد.
TypeScript
این انواع شکل ذخیرهسازی را توصیف میکنند و هر کدام فیلدهایش را به ترتیبی که فایل مینویسد فهرست میکند. فیلدی که با ? علامت خورده فیلدی است که شکل ذخیرهسازی میتواند کنارش بگذارد، همانطور که شکل ذخیرهسازی تفصیل میدهد، و تجزیه فیلد ناموجود را به معنای نداشتن چیزی میخواند: ''، false، نبود گروه جدول یا دامنه، مجموعهٔ خالی، 'physical' برای nameViewMode و دو اسکریپت خالی برای ddlScripts. استثنا فهرست doc ناموجود است که تجزیه آن را از مجموعهاش پر میکند (Doc را ببینید). در یک ردیف واژهنامه، ? مقادیری را علامت میزند که ردیف میتواند پیش از آنها پایان یابد (ردیفهای واژهنامه را ببینید). هر فیلد دیگر همیشه نوشته میشود.
ERDEditorSchemaV3
type ERDEditorSchemaV3 = {
$schema: 'https://raw.githubusercontent.com/dineug/erd-editor/main/json-schema/schema.json';
version: '3.0.0';
settings: Settings;
doc: Doc;
collections?: {
tableEntities?: Record<string, Table>;
tableColumnEntities?: Record<string, Column>;
relationshipEntities?: Record<string, Relationship>;
indexEntities?: Record<string, Index>;
indexColumnEntities?: Record<string, IndexColumn>;
memoEntities?: Record<string, Memo>;
tableGroupEntities?: Record<string, TableGroup>;
wordEntities?: DictionaryRows; // rows of Word
termEntities?: DictionaryRows; // rows of Term
domainEntities?: DictionaryRows; // rows of Domain
};
};
هر موجودیت یک id دارد، یک رشتهٔ غیرشفاف، که کلید آن در مجموعهاش است، بهجز در سه واژهنامه که در آنها id نخستین مقدار یک ردیف است. از نسخهٔ 4.2.0، هنگام تجزیه، برای موجودیتی از هفت مجموعهٔ کلیددار که id آن وجود ندارد، خالی است یا رشته نیست، کلیدی که موجودیت زیر آن نگه داشته شده بهعنوان شناسه خوانده میشود، و مدخلی که شیء نباشد، یا مدخلی بدون شناسه که کلیدش '' است، کنار گذاشته میشود. ردیف واژهنامه وقتی کنار گذاشته میشود که آرایه نباشد یا id آن رشتهای غیر از '' نباشد. ویرایشگرهای پیش از نسخهٔ 4.2.0 موجودیتی را که id آن وجود ندارد یا خالی است کنار میگذارند، بنابراین شکل ذخیرهسازی همچنان همهٔ شناسهها را مینویسد.
از نسخهٔ 4.0.0، هر شناسهٔ جدید، از جمله شناسهٔ ردیفهای واژهنامه، یک UUIDv7 است که به شکل Uuid25 نوشته میشود، یعنی 25 رقم مبنای 36 با حروف کوچک مانند 03gzrxjv20bdlcak89q25d2m7، بنابراین شناسههایی که یک ویرایشگر میسازد به همان ترتیبی مرتب میشوند که ساخته شدهاند. هر سند شناسههایی را که دارد نگه میدارد، مانند شناسههای nanoid نسخهای قدیمیتر یا شناسههای یک فایل v2، بنابراین هیچ چیز نباید به شکل شناسهها وابسته باشد.
از نسخهٔ 4.0.0، هیچ موجودیتی شیء meta (createAt، updateAt) ندارد و نوعهای EntityMeta و EntityType حذف شدهاند. هیچ چیز آن را نمینویسد، هنگام تجزیه شیء meta فایلهای قدیمیتر کنار گذاشته میشود و JSON Schema آن را رد میکند. تنها کاربرد آن زمانبندی جمعآوری زبالهٔ موجودیتهای حذفشده بود که آن هم دیگر وجود ندارد.
Settings
type Settings = {
originX: number;
originY: number;
zoomLevel: number;
show: number; // Constants: Show
database: number; // Constants: Database
databaseName: string;
canvasType: string; // Constants: CanvasType
language: number; // Constants: Language
tableNameCase: number; // Constants: NameCase
columnNameCase: number; // Constants: NameCase
bracketType: number; // Constants: BracketType
relationshipDataTypeSync: boolean;
columnOrder: number[]; // Constants: ColumnType
maxWidthComment: number;
lockSettings: number; // Constants: LockSettingType
ddlScripts?: DDLScripts;
nameViewMode?: string; // Constants: NameViewMode
};
type DDLScripts = {
before: string;
after: string;
};
// Constants
const CanvasType = {
ERD: 'ERD',
visualization: '@dineug/erd-editor/builtin-visualization',
schemaSQL: '@dineug/erd-editor/builtin-schema-sql',
generatorCode: '@dineug/erd-editor/builtin-generator-code',
settings: 'settings',
dictionary: '@dineug/erd-editor/builtin-dictionary',
} as const;
const Show = {
tableComment: 1,
columnComment: 2,
columnDataType: 4,
columnDefault: 8,
columnAutoIncrement: 16,
columnPrimaryKey: 32,
columnUnique: 64,
columnNotNull: 128,
relationship: 256,
columnAlternateKey: 512,
hideReferentialAction: 1024,
hideTableGroup: 2048,
hideMemo: 4096,
columnDomain: 8192,
} as const;
const ColumnType = {
columnName: 1,
columnDataType: 2,
columnNotNull: 4,
columnUnique: 8,
columnAutoIncrement: 16,
columnDefault: 32,
columnComment: 64,
columnLogicalName: 128,
columnDomain: 256,
} as const;
const Database = {
MariaDB: 1,
MSSQL: 2,
MySQL: 4,
Oracle: 8,
PostgreSQL: 16,
SQLite: 32,
Databricks: 64,
Snowflake: 128,
} as const;
const Language = {
GraphQL: 1,
csharp: 2,
Java: 4,
Kotlin: 8,
TypeScript: 16,
JPA: 32,
Scala: 64,
Go: 128,
SQLAlchemy: 256,
TypeORM: 512,
Sequelize: 1024,
Drizzle: 2048,
DBML: 4096,
AML: 8192,
Mermaid: 16384,
PHP: 32768,
Doctrine: 65536,
Rust: 131072,
SeaORM: 262144,
Swift: 524288,
Zod: 1048576,
JSONSchema: 2097152,
} as const;
const NameCase = {
none: 1,
camelCase: 2,
pascalCase: 4,
snakeCase: 8,
} as const;
const BracketType = {
none: 1,
doubleQuote: 2,
singleQuote: 4,
backtick: 8,
} as const;
const LockSettingType = {
viewport: 1, // originX, originY and zoomLevel
canvasType: 2,
language: 4,
tableNameCase: 8,
columnNameCase: 16,
bracketType: 32,
unlockNameViewMode: 64, // nameViewMode; set while unlocked
} as const;
const NameViewMode = {
physical: 'physical',
logical: 'logical',
both: 'both',
} as const;
originX و originY نما هستند: نقطهای از صفحهٔ نمایش که نقطهٔ (0, 0) صحنه روی آن قرار میگیرد.
zoomLevel از 0.1 تا 1.5 است. سندی که با مقداری بیش از 1 ذخیره شده، در ویرایشگرهای پیش از نسخهٔ 3.5.0 با مقدار 1 باز میشود.
از نسخهٔ 4.0.0، تنظیمات هیچیک از width، height، scrollTop، scrollLeft، relationshipOptimization یا ignoreSaveSettings را ندارند. هیچ چیز آنها را نمینویسد، تجزیهگر هیچیک را نگه نمیدارد و JSON Schema فایلی را که هنوز آنها را دارد رد میکند.
canvasType زبانهای است که سند روی آن باز میشود. سندی که در زبانهٔ مصورسازی ذخیره شده '@dineug/erd-editor/builtin-visualization' را در خود دارد، اما نه اینکه حالت Graph نمایش داده میشد یا حالت Flow، و ویرایشگری که تازه ایجاد شده آن زبانه را در حالت Graph نشان میدهد.
از نسخهٔ 4.0.0، تا وقتی قفل Canvas Type روشن است، همانطور که در سند جدید روشن است، سند زبانهای را که هنگام قفل شدن نمایش داده میشد نگه میدارد و جابهجایی میان زبانهها value را دستنخورده میگذارد. قفلی که در زبانهٔ تنظیمات گرفته شود زبانهای را نگه میدارد که خواننده از آن آمده بود، و 'settings' قفلشده، که فقط ویرایش دستی میتواند آن را بنویسد، روی 'ERD' باز میشود.
از نسخهٔ 4.2.0، canvasType میتواند '@dineug/erd-editor/builtin-dictionary' نیز باشد، یعنی زبانهٔ واژهنامه، که قفل Canvas Type آن را مانند زبانههای دیگر نگه میدارد. ویرایشگرهای پیش از نسخهٔ 4.2.0 این مقدار را نگه میدارند، اما تا وقتی خواننده زبانهای را انتخاب نکند، هیچ زبانهای زیر نوار ابزارشان نشان نمیدهند.
هیچ بخشی از وضعیت خود حالت Flow سریالسازی نمیشود: چیدمان، بزرگنمایی، جابهجایی نما، نمایش ردیف و جدولهای مورد تمرکز آن در ویرایشگر میمانند و از نسخهٔ 4.2.0، نماهایی که Previous table و Next table میان آنها گام برمیدارند نیز همینطور. بنابراین originX، originY و zoomLevel همیشه بوم ERD را توصیف میکنند.
show و lockSettings ماسک بیتی هستند — پرچمها را با OR با هم ترکیب کنید.
columnOrder آرایهای است که هر مقدار ColumnType را یک بار و به ترتیب نمایش در خود دارد؛ از نسخهٔ 4.2.0، سند میتواند آن را با هفت مقدار از نه مقدار بنویسد، همانطور که بند مربوط به ترتیب ستونها در پایین توضیح میدهد.
database، language، tableNameCase، columnNameCase و bracketType هر کدام دقیقاً یک مقدار دارند و JSON Schema مقدار ترکیبی را رد میکند.
مقدار show در سند جدید 431 است: tableComment، columnComment، columnDataType، columnDefault، columnPrimaryKey، columnNotNull و relationship.
از نسخهٔ 3.10.0، دو پرچم دیگر برای show وجود دارد که هر دو در سند جدید و در همهٔ سندهایی که پیش از نسخهٔ 3.10.0 ذخیره شدهاند خاموشاند.
columnAlternateKey (512) گزینهٔ نمایش Alternate Key است. وقتی تنظیم شده باشد، ستونهای هر شاخص یکتا روی دو ستون یا بیشتر را با AK1.1، AK1.2 و غیره علامت میزند. در ابتدا خاموش است، بنابراین عرض هیچ نمودار موجودی تغییر نمیکند.
hideReferentialAction (1024) برعکس عمل میکند: وقتی تنظیم شده باشد، برچسبهای ON DELETE و ON UPDATE را روی خطوط اتصال پنهان میکند، بنابراین این برچسبها بهطور پیشفرض نمایش داده میشوند. گزینهٔ نمایش Referential Actions تا وقتی این پرچم خاموش است علامتخورده است. این پرچم اندازهٔ هیچ جدولی را تغییر نمیدهد.
ویرایشگرهای پیش از نسخهٔ 3.10.0 مقدار show را بهصورت یک عدد کامل نگه میدارند، بنابراین هر دو پرچم پس از ذخیره در آنها باقی میمانند.
از نسخهٔ 4.0.0، دو پرچم دیگر برای show وجود دارد که هر دو در سند جدید و در همهٔ سندهایی که پیش از نسخهٔ 4.0.0 ذخیره شدهاند خاموشاند. هر کدام، مانند hideReferentialAction، همان چیزی را که نامش را میبرد پنهان میکند، بنابراین گروههای جدول و یادداشتها بهطور پیشفرض نمایش داده میشوند.
hideTableGroup (2048) گروههای جدول را پنهان میکند و hideMemo (4096) همهٔ یادداشتها را. این دو گزینههای نمایش Table Groups و Memos هستند که هر کدام تا وقتی پرچمش خاموش است علامتخورده است. هیچکدام اندازهٔ هیچ جدولی را تغییر نمیدهد.
ویرایشگرهای پیش از نسخهٔ 4.0.0 مقدار show را بهصورت یک عدد کامل نگه میدارند، بنابراین هر دو پرچم پس از ذخیره در آنها باقی میمانند.
از نسخهٔ 4.2.0، یک پرچم دیگر برای show وجود دارد، columnDomain (8192)، که در سند جدید و در همهٔ سندهایی که پیش از نسخهٔ 4.2.0 ذخیره شدهاند خاموش است، بنابراین مقدار show در سند جدید همچنان 431 است. این پرچم گزینهٔ نمایش Domain است: وقتی تنظیم شده باشد، هر ردیف ستون یک خانهٔ دامنه نشان میدهد که جدولها را پهنتر میکند. در ابتدا خاموش است، بنابراین عرض هیچ نمودار موجودی تغییر نمیکند.
ویرایشگرهای پیش از نسخهٔ 4.2.0 مقدار show را بهصورت یک عدد کامل نگه میدارند، بنابراین این پرچم پس از ذخیره در آنها باقی میماند.
از نسخهٔ 4.2.0، ColumnType شامل نه مقدار است. columnLogicalName (128) جای خانهٔ نام منطقی را تعیین میکند که ردیف ستون فقط در نمای Both Names آن را نشان میدهد، و columnDomain (256) جای خانهٔ دامنه را. این دو، ردیفهای Logical Name و Domain در ترتیب ستونها در زبانهٔ تنظیمات هستند. ویرایشگر ترتیبی از هر نه مقدار را نگه میدارد و ترتیب سند جدید 128, 1, 2, 256, 4, 8, 16, 32, 64 است.
شکل ذخیرهسازی، تا وقتی 128 درست پیش از columnName و 256 درست پس از columnDataType قرار دارد، ترتیب را با هفت مدخل و بدون 128 و 256 مینویسد. بنابراین سند جدید همچنان 1, 2, 4, 8, 16, 32, 64 را مینویسد و فایلی که ترتیبش هرگز این دو را جابهجا نکرده بایتهایش را حفظ میکند. در غیر این صورت هر نه مقدار را مینویسد.
هنگام تجزیه، این دو در ترتیبی هفتمدخلی، با هر ترتیبی که آن هفت مقدار داشته باشند، در همان جایگاهها قرار داده میشوند و ترتیبی با نه مدخل که همهٔ انواع را در بر داشته باشد همانطور که هست پذیرفته میشود.
از نسخهٔ 5.0.0 ترتیبهای دیگر را هم میپذیرد. هر ColumnType شناختهشده را یک بار و به همان ترتیبی که آمده نگه میدارد و هر مدخل دیگری را کنار میگذارد: مقداری که هیچ ColumnType آن را نام نمیبرد، مانند نوعی که نسخهای بعدی اضافه میکند، و مدخل دوم یک نوع. هر نوعی که ترتیب فاقد آن است درست پس از نزدیکترین نوعِ پیش از آن در ترتیب پیشفرض قرار میگیرد که ترتیب دارد، یا اگر پیش از آن هیچکدام نیست، درست پیش از نزدیکترین نوع پس از آن؛ همینطور 128 و 256 در هفت مدخل جای خود را پیدا میکنند. فقط ترتیبی که هیچ نوع شناختهشدهای را نام نمیبرد، یا مقداری که آرایه نیست، ترتیب پیشفرض خوانده میشود.
بنابراین فایلی که نسخهای بعدی ذخیره کرده با ترتیب انواعی که این نسخه میشناسد باز میشود و ذخیره در این نسخه آن ترتیب را بدون بقیه مینویسد. پیش از 5.0.0 تجزیه هر ترتیب دیگر را پیشفرض میخواند، پس چنین فایلی با ترتیب ستون بازنشانیشده باز میشد. JSON Schema هفت یا نه عدد صحیح را میپذیرد.
از نسخهٔ 4.0.0، Language هشت هدف دیگر برای مولد کد دارد، از Mermaid تا JSONSchema. مقداری از language که تجزیهگر آن را نمیشناسد GraphQL خوانده میشود، بنابراین ویرایشگرهای پیش از نسخهٔ 4.0.0 سندی را که با یکی از این هدفها ذخیره شده روی GraphQL باز میکنند و ذخیره در آنها GraphQL را مینویسد.
از نسخهٔ 4.0.0، lockSettings جای ignoreSaveSettings را گرفته است و LockSettingType جای SaveSettingType را که حذف شده است. lockSettings تنظیماتی را مشخص میکند که سند آنها را همانطور ذخیره میکند که هنگام قفل شدن بودند. بیت viewport فیلدهای originX، originY و zoomLevel را با هم پوشش میدهد، زیرا مبدئی که بدون سطح بزرگنماییاش ذخیره شود جای دیگری باز میشود، و هر بیت دیگر فیلدی را پوشش میدهد که همنام آن است. اینها ردیفهای Lock در زبانهٔ تنظیمات هستند.
فایل هر تنظیم قفلشده را، هر چه ویرایشگر نشان دهد، با مقدار قفلشدهاش در خود دارد و هر تنظیم دیگر را با مقدار فعلیاش. بنابراین تا وقتی قفل متناظر روشن است، پیمایش و بزرگنمایی، جابهجایی میان زبانهها، تغییر زبان کد در مولد کد، شیوهٔ نگارش نام یا نوع علامت نقلقول، یا تغییر نمایش نامها، فایل را دستنخورده میگذارد. قفل کردن مقداری را که تنظیم در آن لحظه دارد ثبت میکند، و هنگام تجزیه مقدار قفلشده از فیلد ذخیرهشده خوانده میشود.
سندی که از صفر شروع میشود — ویرایشگر یا مخزن رونوشت جدید، یا مقداری خالی که به value یا setInitialValue() داده شود — مقدار lockSettings آن 63 است، یعنی همهٔ قفلها روشناند. سندی که settings آن فیلد lockSettings ندارد — همهٔ فایلهایی که پیش از نسخهٔ 4.0.0 ذخیره شدهاند، با هر مقدار ignoreSaveSettings، و همهٔ سندهای v2 — نیز با همهٔ قفلهای روشن باز میشود: نما و زبانهاش همانند سند جدید است (originX و originY برابر 0، zoomLevel برابر 1، زبانهٔ ERD) و زبان کد، شیوههای نگارش نام و نوع علامت نقلقولش روی مقادیری که ذخیره کرده قفل میشوند. سندی که قفلهایش را مشخص کرده است آنها را، از جمله 0، همراه با همهٔ مقادیری که ذخیره کرده نگه میدارد.
هنگام تجزیه همهٔ بیتهای lockSettings، حتی بیتهای ناشناخته، حفظ میشوند، بنابراین قفلی که نسخهای جدیدتر اضافه کند پس از ذخیره در اینجا باقی میماند؛ JSON Schema فقط بررسی میکند که این مقدار عدد صحیح باشد. ویرایشگرهای پیش از نسخهٔ 4.0.0 هنگام ذخیره فیلد lockSettings را کنار میگذارند و نما و زبانه را همانطور که هستند مینویسند، بنابراین فایل در اینجا دوباره مانند فایلی باز میشود که پیش از نسخهٔ 4.0.0 ذخیره شده است.
از نسخهٔ 4.2.0، قفل هفتمی وجود دارد، unlockNameViewMode (64)، یعنی ردیف Name View، که nameViewMode را پوشش میدهد. بیت آن، مانند بیتهای پنهانسازی Show، برعکس بیتهای قفل دیگر خوانده میشود: وقتی تنظیم شده باشد، نمایش نامها بدون قفل است و وقتی پاک باشد، قفل است. بنابراین 63 همچنان به معنای روشن بودن همهٔ قفلهاست و سند جدید همین مقدار را دارد، در حالی که نمایش نامها روی 'physical' قفل است. فایلی که پیش از نسخهٔ 4.2.0 ذخیره شده، با هر وضعیتی از قفلهای دیگرش، از جمله 0، این بیت را پاک دارد، بنابراین در حالی باز میشود که نمایش نامها روی 'physical' قفل است. سندی که همهٔ قفلهایش خاموش است 64 را دارد و سندی که همهٔ قفلهای دیگرش روشن و نمایش نامها در آن بدون قفل است 127 را. این قفل را معکوس بررسی کنید: تا وقتی (lockSettings & 64) === 0 باشد، روشن است.
تا وقتی بیت پاک است، فایل nameViewMode را، هر چه هر ویرایشگری نشان دهد، با نمای قفلشده در خود دارد و تا وقتی بیت تنظیم شده است، با نما به همان صورت که هست. اینکه هر ویرایشگر، با قفل روشن یا خاموش، چه نشان میدهد در Lock توضیح داده شده است.
ویرایشگر نسخهٔ 4.0.0 یا 4.1.0 این بیت را هنگام ذخیره نگه میدارد اما nameViewMode را کنار میگذارد، بنابراین سند در اینجا با 'physical' و با همان وضعیت قفل پیشین دوباره باز میشود.
از نسخهٔ 4.0.0، ddlScripts دو اسکریپت زبانهٔ طرحواره SQL را در خود دارد که DDL همهٔ پایگاههای داده آنها را مینویسد: before را پس از سرآیند و پیش از جدولها و after را پس از DDL تولیدشده. DDL هر یک را با شکست خط LF، بدون خطوط خالی ابتدایی و فاصلههای انتهاییاش و در MSSQL با GO در پایان مینویسد، همانطور که در اسکریپتهای پیش و پس از جدولها توضیح داده شده است؛ خود ddlScripts هر اسکریپت را همانطور که تایپ شده نگه میدارد. این کلید فقط تا وقتی یکی از دو اسکریپت متن دارد نوشته میشود و در آن صورت با هر دو اسکریپت؛ نبود کلید یا اسکریپتی که رشته نباشد '' خوانده میشود. گزینههای Statements، Header و Tables این زبانه و از نسخهٔ 4.2.0، گزینهٔ Write logical names into empty comments آن، در سند ذخیره نمیشوند.
ویرایشگرهای پیش از نسخهٔ 4.0.0 هنگام بارگذاری سند اسکریپتها را کنار میگذارند، بنابراین ذخیره در آنها اسکریپتها را از بین میبرد.
از نسخهٔ 4.2.0، nameViewMode همان نمایش نامها است، یعنی نامهایی که نمودار نشان میدهد: 'physical' نام هر جدول و ستون، 'logical' نام منطقی آن بهجای نام و 'both' نام منطقی و نام. منوها آنها را Physical Names، Logical Names و Both Names مینامند. شکل ذخیرهسازی آن را در آخر، پس از ddlScripts، و فقط تا وقتی مقداری که مینویسد 'physical' نیست مینویسد. مقدار ناموجود، یا مقداری که تجزیهگر نمیشناسد، 'physical' خوانده میشود و JSON Schema فقط "logical" و "both" را میپذیرد.
ویرایشگرهای پیش از نسخهٔ 4.2.0 هنگام بارگذاری سند nameViewMode را کنار میگذارند.
به Database، Language، Show، ColumnType، ColumnOption، LockSettingType و ReferentialAction فقط میتوان از انتها افزود. سند ذخیرهشده عدد را نگه میدارد، بنابراین سامانهٔ پایگاه داده، هدف تولید کد، پرچم، نوع ستون، گزینهٔ ستون، قفل یا کنش جدید بیت بعدی را میگیرد، نه جایی در میانه را.
Doc
type Doc = {
tableIds?: string[];
relationshipIds?: string[];
indexIds?: string[];
memoIds?: string[];
tableGroupIds?: string[];
};
هر فهرست ترتیب یک نوع موجودیت است که DDL، مرتبسازی جدولها و ترتیب رسم آن را میخوانند. هر فهرست فقط شناسههای موجودیتهایی را دارد که فایل مینویسد، هر کدام یک بار و به همان ترتیبی که فهرست شدهاند، و از نسخهٔ 4.2.0، فهرستی که هیچ شناسهای ندارد کنار گذاشته میشود. از نسخهٔ 4.0.0، tableGroupIds ترتیب گروههای جدول است. واژهنامهها در اینجا فهرستی ندارند، چون ردیفهایشان به ترتیب هر برگه قرار دارند (ردیفهای واژهنامه را ببینید)، و JSON Schema هیچ کلید دیگری را در doc نمیپذیرد.
از نسخهٔ 4.2.0، هنگام تجزیه، فهرستی که سند کنار گذاشته است، یا به شکلی غیر از آرایه دارد، بهصورت همهٔ مدخلهایی که مجموعهاش دارد خوانده میشود، هر شناسه یک بار و به همان ترتیبی که نگه داشته شدهاند؛ آرایهٔ خالی خالی میماند و در آن صورت همهٔ مدخلهای مجموعهاش حذفشده خوانده میشوند. ویرایشگرهای پیش از نسخهٔ 4.2.0 فهرست ناموجود را خالی میخوانند، بنابراین شکل ذخیرهسازی همچنان هر فهرست را هر زمان که مجموعهاش موجودیتی داشته باشد مینویسد.
از نسخهٔ 4.0.0، فایل ترتیب لایهها را در خود ندارد. بارگذاری جدولها و یادداشتهای فهرستشده را بر اساس جایگاهشان در فهرستهایشان در لایهها میچیند، موارد بعدی جلوتر و هر یادداشت بالاتر از هر جدول، و گروههای جدول را نیز به همین شیوه در میان خودشان، پشت جدولها. جدول یا یادداشت در فایلی که پیش از نسخهٔ 4.0.0 ذخیره شده در ui خود یک zIndex دارد که بارگذاری آن را بهعنوان جایگاهش در پشته نگه میدارد و ذخیرهٔ بعدی کنارش میگذارد. بنابراین آوردن یک جدول یا یادداشت به جلو با باز کردن دوبارهٔ فایل از بین میرود.
مجموعه: tableEntities
type Table = {
id: string;
name?: string;
logicalName?: string;
comment?: string;
columnIds: string[];
groupId?: string;
nameDerived?: true;
ui: TableUI;
};
type TableUI = {
x: number;
y: number;
color?: string;
};
از نسخهٔ 4.0.0، هر جدول groupId دارد، یعنی شناسهٔ گروه جدولی که به آن تعلق دارد. نبودن groupId، خالی بودن آن یا اشاره نکردن آن به هیچ گروهی در doc.tableGroupIds به معنای نداشتن گروه است و شکل ذخیرهسازی آن را فقط تا وقتی به گروهی باقیمانده اشاره میکند مینویسد.
از نسخهٔ 4.2.0، هر جدول logicalName دارد، یعنی نامی که نماهای Logical Names و Both Names نشان میدهند، و '' برای نبود آن، و nameDerived که تا وقتی واژهنامهها name را از نام منطقی استخراج کردهاند true است. تا وقتی تنظیم شده است، نام منطقی جدید نام را دوباره استخراج میکند؛ تا وقتی تنظیم نشده است، نام را کسی خودش نوشته است و نام منطقی جدید آن را دستنخورده میگذارد، مگر اینکه نام خالی یا فقط فاصله باشد. تغییر نام دستی آن را خاموش میکند و Derive Physical Names Again حتی نامی را که کسی نوشته است بازنویسی میکند و هر جا نام منطقی وجود داشته باشد آن را روشن میکند.
شکل ذخیرهسازی logicalName را پس از name، همانطور که تایپ شده، فقط تا وقتی متنی غیر از فاصله دارد مینویسد، و nameDerived را پس از groupId فقط تا وقتی true است، که تنها مقداری است که JSON Schema میپذیرد. logicalName ناموجود '' و nameDerived ناموجود false خوانده میشود، بنابراین هر نامی در فایلی که پیش از نسخهٔ 4.2.0 ذخیره شده، نامی به شمار میآید که کسی خودش نوشته است.
ویرایشگرهای پیش از نسخهٔ 4.2.0 هنگام بارگذاری سند هر دو را کنار میگذارند، بنابراین ذخیره در آنها نام منطقی همهٔ جدولها را از بین میبرد.
مجموعه: tableColumnEntities
type Column = {
id: string;
tableId: string;
name?: string;
comment?: string;
dataType?: string;
default?: string;
options: number; // Constants: ColumnOption
logicalName?: string;
domainId?: string;
};
// Constants
const ColumnOption = {
autoIncrement: 1,
primaryKey: 2,
unique: 4,
notNull: 8,
nameDerived: 16,
} as const;
از نسخهٔ 4.0.0 فایل نشانههای کلید را در خود ندارد: هر بارگذاری یک ستون را از روی بیت primaryKey در options کلید اصلی علامت میزند، و تا وقتی رابطهای در جدولش به آن ختم میشود، کلید خارجی.
ویرایشگرهای پیش از نسخهٔ 4.0.0 ستونهای فایلی را که در اینجا ذخیره شده بدون نماد کلید اصلیشان نشان میدهند.
از نسخهٔ 4.2.0، هر ستون، مانند جدول، logicalName دارد و نیز domainId، یعنی شناسهٔ دامنهای که ستون به آن پیوند خورده است، و '' برای نبود آن. ویرایشها در یک ویرایشگر ستون پیوندخورده را روی نوع دادهٔ دامنهاش نگه میدارند، همانطور که در دامنهها و انواع داده توضیح داده شده است. با این حال تجزیه نوع هیچ ستونی را تغییر نمیدهد، بنابراین فایلی که جای دیگری نوشته شده ممکن است ستون پیوندخوردهای را با نوع دیگری باقی بگذارد و ویرایشهای متقاطع دو همکار نیز ممکن است چنین کنند؛ برگهٔ بررسیها هر کدام را با بررسی Domain type mismatch فهرست میکند. هنگام تجزیه، domainId که به هیچ دامنهای در فایل اشاره نکند پاک میشود. شکل ذخیرهسازی پس از options، logicalName را طبق قاعدهٔ جدول و domainId را فقط تا وقتی به دامنهای اشاره میکند که فایل آن را مینویسد، مینویسد، بنابراین ستونی را که به دامنهای حذفشده، یا به دامنهای که فایل کنار میگذارد، پیوند خورده بدون پیوند و با نوع دادهٔ فعلیاش مینویسد.
ColumnOption.nameDerived (16) پرچم نام استخراجشدهٔ ستون است که همراه با بیتهای دیگر در options نگه داشته میشود و همان معنایی را دارد که nameDerived جدول. برای نمونه، کلید اصلی غیر NULL که واژهنامهها نامش را استخراج کردهاند، options برابر 26 دارد.
ویرایشگرهای پیش از نسخهٔ 4.2.0 هنگام بارگذاری سند logicalName و domainId را کنار میگذارند، بنابراین ذخیره در آنها این دو را از بین میبرد. این ویرایشگرها options را بهصورت یک عدد کامل نگه میدارند، بنابراین بیت nameDerived پس از ذخیره در آنها باقی میماند.
مجموعه: relationshipEntities
type Relationship = {
id: string;
relationshipType: number; // Constants: RelationshipType
onDelete: number; // Constants: ReferentialAction
onUpdate: number; // Constants: ReferentialAction
start: RelationshipPoint;
end: RelationshipPoint;
};
type RelationshipPoint = {
tableId: string;
columnIds: string[];
};
// Constants
const RelationshipType = {
ZeroOne: 2,
ZeroN: 4,
OneOnly: 8,
OneN: 16,
} as const;
const ReferentialAction = {
none: 1,
noAction: 2,
cascade: 4,
setNull: 8,
setDefault: 16,
restrict: 32,
} as const;
از نسخهٔ 3.10.0، هر رابطه onDelete و onUpdate را دارد که کنشهای ON DELETE و ON UPDATE آن هستند. هر کدام دقیقاً یک مقدار ReferentialAction دارد. none، که پیشفرض است، هیچ بندی نمینویسد، بنابراین پیشفرض خود پایگاه داده اعمال میشود. پنج مقدار دیگر نمایانگر NO ACTION، CASCADE، SET NULL، SET DEFAULT و RESTRICT هستند. طرحواره SQL بند را فقط برای پایگاه دادهای مینویسد که کنش آن را بپذیرد.
شکل ذخیرهسازی همیشه هر دو را مینویسد و از نسخهٔ 4.0.0، JSON Schema آنها را الزامی میداند و فقط بررسی میکند که هر کدام عدد صحیح باشد. هنگام تجزیه، فیلد ناموجود، مانند آنچه در همهٔ سندهای ذخیرهشده پیش از نسخهٔ 3.10.0 پیش میآید، همچنان none خوانده میشود و مقداری خارج از فهرست نیز همینطور.
ویرایشگرهای پیش از نسخهٔ 3.10.0 این فیلدها را نمیشناسند و هنگام بارگذاری سند آنها را کنار میگذارند، بنابراین ذخیره در آنها همهٔ کنشها را از بین میبرد.
از نسخهٔ 4.0.0، هر بارگذاری شناسا بودن رابطه و شیوهٔ رسم انتهای والد آن را از ستونهایی که رابطه به آنها ختم میشود و جدول فرزند هنوز فهرستشان میکند میخواند. تا وقتی همهٔ این ستونها کلید اصلی باشند شناسا است، با خط پر، و انتهای والد آن تا وقتی همهٔ این ستونها NOT NULL باشند دو خط است و در غیر این صورت یک حلقه و یک خط. رابطهای که هیچ چنین ستونی برایش نمانده غیرشناسا با دو خط است، همانطور که هر رابطهٔ جدید در آغاز چنین است. خواندن خط اتصال را ببینید.
مجموعه: indexEntities
type Index = {
id: string;
name?: string;
tableId: string;
indexColumnIds: string[];
unique: boolean;
};
مجموعه: indexColumnEntities
type IndexColumn = {
id: string;
indexId: string;
columnId: string;
orderType: number; // Constants: OrderType
};
// Constants
const OrderType = {
ASC: 1,
DESC: 2,
} as const;
مجموعه: memoEntities
type Memo = {
id: string;
value?: string;
ui: MemoUI;
};
type MemoUI = {
x: number;
y: number;
width: number;
height: number;
color?: string;
};
از نسخهٔ 4.0.0، جدولها و یادداشتها در یک پشتهٔ مشترک قرار دارند، بنابراین آوردن یک جدول به جلو میتواند آن را روی یک یادداشت قرار دهد. بارگذاری هر یادداشت را بالاتر از هر جدول قرار میدهد، همانطور که در Doc توضیح داده شده است. یادداشتی که در فایلی ذخیرهشده پیش از نسخهٔ 4.0.0 است zIndex ذخیرهشدهٔ خود را نگه میدارد که از همان شمارندهٔ جدولها آمده است، بنابراین یادداشتی که نسخهای قدیمیتر روی همهٔ جدولها رسم کرده بود ممکن است زیر جدولی باز شود که پس از آن به جلو آورده شده است.
مجموعه: tableGroupEntities
type TableGroup = {
id: string;
name?: string;
color?: string;
ui: TableGroupUI;
};
type TableGroupUI = {
x: number;
y: number;
width: number;
height: number;
};
از نسخهٔ 4.0.0، سند میتواند گروههای جدول داشته باشد: مستطیلهای نامدار و رنگی که پشت جدولها رسم میشوند. هر جدول از طریق groupId خودش به یک گروه میپیوندد، بنابراین گروه فهرستی از اعضا ندارد. شکل ذخیرهسازی این مجموعه را، مانند doc.tableGroupIds، فقط تا وقتی گروهی وجود دارد مینویسد، و سندی که آن را ندارد، مانند سندی که پیش از نسخهٔ 4.0.0 ذخیره شده، هیچ گروهی ندارد. Show.hideTableGroup آنها را پنهان میکند.
ویرایشگرهای پیش از نسخهٔ 4.0.0 هنگام بارگذاری سند گروهها و groupId همهٔ جدولها را کنار میگذارند، بنابراین ذخیره در آنها همهٔ گروهها را از بین میبرد.
ردیفهای واژهنامه
از نسخهٔ 4.2.0، هر سند سه واژهنامه دارد، یعنی برگههای Words، Terms و Domains در زبانهٔ واژهنامه، که در wordEntities، termEntities و domainEntities قرار دارند. هر فیلد یک واژه، اصطلاح یا دامنه یک رشته است و هیچکدام ui ندارند. برگهٔ Checks از واژهنامهها و نمودار محاسبه میشود و ذخیره نمیشود.
type DictionaryRows = {
fields: string[];
rows: string[][];
};
هیچیک از این سه با شناسه کلیدگذاری نمیشود. هر کدام بهصورت یک سرآیند و ردیفها نوشته میشود: fields فیلدهای موجودیت را یک بار، با شناسه در ابتدا، نام میبرد و هر ردیف مقادیر یک موجودیت را به همان ترتیب در خود دارد. انواع زیر فیلدهای هر موجودیت را به همان ترتیب فهرست میکنند. هر ردیف همیشه شناسه و نام خود را نگه میدارد، اما مقادیر خالی انتهایی آن پس از نام کنار گذاشته میشوند، بنابراین مقدار خالیای که پیش از یک مقدار نگهداشتهشده قرار دارد '' میماند و هنگام تجزیه، مقداری که ردیف ندارد '' خوانده میشود. هر ردیف در خطی جداگانه بهصورت JSON فشرده نوشته میشود، مانند این دو واژه از یک فایل:
"wordEntities": {
"fields": [
"id",
"name",
"abbreviation",
"englishName",
"description",
"synonyms",
"forbiddenWords"
],
"rows": [
["w1","Customer","CUST","customer"],
["w2","Number","NO","number","","No, Num","Nbr"]
]
}
شکل ذخیرهسازی ردیفهای هر برگه را به ترتیب همان برگه و بدون فیلد ترتیب مینویسد، بنابراین ردیفهای یک فایل هم اعضای یک واژهنامهاند و هم ترتیب آنها. ردیفی را که همهٔ مقادیرش بهجز شناسه خالی یا فقط فاصله باشند، مانند ردیفی که اضافه شده و هرگز پر نشده یا خالی شده است، و هر پیوند به چنین دامنهای یا به دامنهای حذفشده را کنار میگذارد: domainId ستون کنار گذاشته میشود و domainId اصطلاح '' نوشته میشود و اگر خود اصطلاح چیز دیگری نداشته باشد، کنار گذاشته میشود.
هنگام تجزیه، ردیفها به ترتیبی که قرار دارند خوانده میشوند، بنابراین هر برگه آنها را به ترتیبی که فایل نوشته است فهرست میکند.
سندی که واژهنامهها را ندارد، مانند سندی که پیش از نسخهٔ 4.2.0 ذخیره شده، هیچ واژهنامهای ندارد. ویرایشگرهای پیش از نسخهٔ 4.2.0 هنگام بارگذاری سند هر سه را کنار میگذارند، بنابراین ذخیره در آنها همهٔ واژهها، اصطلاحات و دامنهها را از بین میبرد.
مجموعه: wordEntities
type Word = {
id: string;
name: string;
abbreviation?: string;
englishName?: string;
description?: string;
synonyms?: string;
forbiddenWords?: string;
};
واژه یکی از واژههایی است که نام منطقی از آنها ساخته میشود و abbreviation چیزی است که در نام فیزیکی جای آن میآید. synonyms شکلهای دیگر نوشتن واژه را فهرست میکند و forbiddenWords واژههایی را که نباید بهجای آن به کار روند، هر کدام جداشده با ویرگول.
مجموعه: termEntities
type Term = {
id: string;
name: string;
physicalName?: string;
domainId?: string;
description?: string;
synonyms?: string;
};
اصطلاح یک نام منطقی کامل است. جدول یا ستونی که logicalName آن با name منطبق باشد، physicalName را بهعنوان نام استخراج میکند، یا تا وقتی آن خالی است، نامی ساختهشده از اختصارهای واژهها را، و ستون دامنهای را نیز میگیرد که domainId نام میبرد و برای نبود دامنه '' است (استخراج نامهای فیزیکی را ببینید). synonyms با ویرگول جدا میشود. هنگام تجزیه، domainId که به هیچ دامنهای در فایل اشاره نکند پاک میشود، همانطور که در ستون.
مجموعه: domainEntities
type Domain = {
id: string;
name: string;
category?: string;
dataType?: string;
description?: string;
};
دامنه یک نوع دادهٔ نامدار است و dataType آن را مانند ستون، همراه با طول، نگه میدارد، برای نمونه NUMERIC(10). ستون یا اصطلاح با شناسهٔ دامنه به آن پیوند داده میشود و ویرایشگر نوع دادهٔ دامنه را به هر ستون پیوندخورده میدهد (دامنهها و انواع داده را ببینید).
JSON Schema
فایل طرحوارهٔ مرجع در json-schema/schema.json منتشر شده است و میتوان مستقیماً با $schema به آن ارجاع داد.
{
"$schema": "https://raw.githubusercontent.com/dineug/erd-editor/main/json-schema/schema.json",
"version": "3.0.0"
}
$schema را در بالای فایل .erd.json قرار دهید تا ویرایشگرهایی که JSON Schema را میفهمند، مانند VS Code، هنگام ویرایش سند را اعتبارسنجی کنند و فیلدهایش را تکمیل خودکار کنند.
از نسخهٔ 4.0.0، این طرحواره فقط شکل ذخیرهسازی را توصیف میکند. هر شیء با فیلدهای نامدار بسته است (additionalProperties: false)، هر فیلدی که شکل ذخیرهسازی همیشه مینویسد الزامی است، هر فیلدی که در انواع بالا با ? علامت خورده نام برده شده اما الزامی نیست و هیچ فیلد دیگری نام برده نشده است. بنابراین فایلی را که پیش از نسخهٔ 4.0.0 ذخیره شده، با meta، عرضها، zIndex، ignoreSaveSettings و بقیهٔ فیلدهایش، رد میکند تا وقتی که ویرایشگری با نسخهٔ 4.0.0 یا بالاتر آن فایل را دوباره ذخیره کند. فایلی که نسخهٔ 3.2.0 یا بالاتر ذخیره کرده از قبل نشانی این طرحواره را در خود دارد که به شاخهٔ main اشاره میکند، بنابراین ویرایشگری که بر اساس آن اعتبارسنجی میکند اکنون آن فایل را دارای خطا نشان میدهد. فایلی که نسخهٔ 3.0.0 یا 3.1.0 ذخیره کرده، یا یک سند v2، فیلد $schema ندارد.
از نسخهٔ 4.2.0، این طرحواره دیگر فیلدهای متنی موجودیتها، هیچ فهرست doc، هیچ مجموعه و خود collections را، که شکل ذخیرهسازی تا وقتی چیزی ندارند کنارشان میگذارد، الزامی نمیداند. همچنان فایلی را که نسخهٔ 4.0.0 یا 4.1.0 ذخیره کرده میپذیرد. فیلدهای جدید را نام میبرد: nameViewMode که فقط "logical" و "both" را میپذیرد؛ logicalName و nameDerived جدول که دومی فقط true را میپذیرد؛ logicalName و domainId ستون؛ و سه واژهنامه، هر کدام با سرآیند و ردیفهایی از رشتهها. canvasType زبانهٔ واژهنامه را فهرست میکند، columnOrder هفت یا نه عدد صحیح را میپذیرد و توضیحات show، columnOrder، lockSettings و options بیتهای جدید را نام میبرند.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/dineug/erd-editor/main/json-schema/schema.json",
"title": "ERD Editor document",
"description": "The storage form an ERD Editor file holds (.erd, .erd.json, .vuerd, .vuerd.json): the live entities alone, each collection keyed in id order but the dictionaries, a header and one row per entry in document order, without what an editor derives on load or keeps while it is open, without an entity's text field while it is empty, which reads as the empty string, and without an empty list or collection, which reads as none",
"type": "object",
"properties": {
"$schema": {
"type": "string"
},
"version": {
"description": "Version of the schema",
"const": "3.0.0"
},
"settings": {
"$ref": "#/$defs/settings"
},
"doc": {
"$ref": "#/$defs/doc"
},
"collections": {
"description": "The entities of each kind, a kind with none left out",
"type": "object",
"properties": {
"tableEntities": {
"$ref": "#/$defs/tableEntities"
},
"tableColumnEntities": {
"$ref": "#/$defs/tableColumnEntities"
},
"relationshipEntities": {
"$ref": "#/$defs/relationshipEntities"
},
"indexEntities": {
"$ref": "#/$defs/indexEntities"
},
"indexColumnEntities": {
"$ref": "#/$defs/indexColumnEntities"
},
"memoEntities": {
"$ref": "#/$defs/memoEntities"
},
"tableGroupEntities": {
"$ref": "#/$defs/tableGroupEntities"
},
"wordEntities": {
"$ref": "#/$defs/wordEntities"
},
"termEntities": {
"$ref": "#/$defs/termEntities"
},
"domainEntities": {
"$ref": "#/$defs/domainEntities"
}
},
"additionalProperties": false
}
},
"required": ["$schema", "version", "settings", "doc"],
"additionalProperties": false,
"$defs": {
"settings": {
"type": "object",
"properties": {
"originX": {
"type": "number"
},
"originY": {
"type": "number"
},
"zoomLevel": {
"type": "number",
"minimum": 0.1,
"maximum": 1.5
},
"show": {
"description": "bit value (tableComment: 1) | (columnComment: 2) | (columnDataType: 4) | (columnDefault: 8) | (columnAutoIncrement: 16) | (columnPrimaryKey: 32) | (columnUnique: 64) | (columnNotNull: 128) | (relationship: 256) | (columnAlternateKey: 512) | (hideReferentialAction: 1024) | (hideTableGroup: 2048) | (hideMemo: 4096) | (columnDomain: 8192); the three hide bits hide what they name while set",
"type": "integer"
},
"database": {
"description": "bit value (MariaDB: 1) | (MSSQL: 2) | (MySQL: 4) | (Oracle: 8) | (PostgreSQL: 16) | (SQLite: 32) | (Databricks: 64) | (Snowflake: 128)",
"type": "integer",
"enum": [1, 2, 4, 8, 16, 32, 64, 128]
},
"databaseName": {
"type": "string"
},
"canvasType": {
"enum": [
"ERD",
"@dineug/erd-editor/builtin-visualization",
"@dineug/erd-editor/builtin-schema-sql",
"@dineug/erd-editor/builtin-generator-code",
"settings",
"@dineug/erd-editor/builtin-dictionary"
]
},
"language": {
"description": "bit value (GraphQL: 1) | (csharp: 2) | (Java: 4) | (Kotlin: 8) | (TypeScript: 16) | (JPA: 32) | (Scala: 64) | (Go: 128) | (SQLAlchemy: 256) | (TypeORM: 512) | (Sequelize: 1024) | (Drizzle: 2048) | (DBML: 4096) | (AML: 8192) | (Mermaid: 16384) | (PHP: 32768) | (Doctrine: 65536) | (Rust: 131072) | (SeaORM: 262144) | (Swift: 524288) | (Zod: 1048576) | (JSONSchema: 2097152)",
"type": "integer",
"enum": [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152]
},
"tableNameCase": {
"description": "bit value (none: 1) | (camelCase: 2) | (pascalCase: 4) | (snakeCase: 8)",
"type": "integer",
"enum": [1, 2, 4, 8]
},
"columnNameCase": {
"description": "bit value (none: 1) | (camelCase: 2) | (pascalCase: 4) | (snakeCase: 8)",
"type": "integer",
"enum": [1, 2, 4, 8]
},
"bracketType": {
"description": "bit value (none: 1) | (doubleQuote: 2) | (singleQuote: 4) | (backtick: 8)",
"type": "integer",
"enum": [1, 2, 4, 8]
},
"relationshipDataTypeSync": {
"type": "boolean"
},
"columnOrder": {
"description": "bit value (columnName: 1) | (columnDataType: 2) | (columnNotNull: 4) | (columnUnique: 8) | (columnAutoIncrement: 16) | (columnDefault: 32) | (columnComment: 64) | (columnLogicalName: 128) | (columnDomain: 256); seven entries without the last two while the logical name stands just before the name and the domain just after the data type, all nine otherwise",
"type": "array",
"prefixItems": [
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" },
{ "type": "integer" }
],
"anyOf": [
{ "minItems": 7, "maxItems": 7 },
{ "minItems": 9, "maxItems": 9 }
]
},
"maxWidthComment": {
"type": "integer"
},
"lockSettings": {
"description": "bit value (viewport: 1) | (canvasType: 2) | (language: 4) | (tableNameCase: 8) | (columnNameCase: 16) | (bracketType: 32) | (unlockNameViewMode: 64); a locked setting is saved as it stood when locked, the viewport being originX, originY and zoomLevel. The last bit reads the other way round: set, the name view mode is unlocked, and clear, as in a file saved before it, locked",
"type": "integer"
},
"ddlScripts": {
"description": "SQL the Schema SQL writes as is for every database: before after the header and ahead of the tables, after past the generated DDL. Absent while both are empty",
"type": "object",
"properties": {
"before": { "type": "string" },
"after": { "type": "string" }
},
"required": ["before", "after"],
"additionalProperties": false
},
"nameViewMode": {
"description": "The names the diagram shows: the logical ones, or both the physical and the logical. Absent while it shows the physical names, the default",
"enum": ["logical", "both"]
}
},
"required": [
"originX",
"originY",
"zoomLevel",
"show",
"database",
"databaseName",
"canvasType",
"language",
"tableNameCase",
"columnNameCase",
"bracketType",
"relationshipDataTypeSync",
"columnOrder",
"maxWidthComment",
"lockSettings"
],
"additionalProperties": false
},
"doc": {
"description": "The order of each kind of entity, which the DDL, the sort and the draw order read, a kind with none left out. A list goes out whenever its collection holds an entity, since a reader that finds none lists none",
"type": "object",
"properties": {
"tableIds": {
"type": "array",
"items": {
"type": "string"
}
},
"relationshipIds": {
"type": "array",
"items": {
"type": "string"
}
},
"indexIds": {
"type": "array",
"items": {
"type": "string"
}
},
"memoIds": {
"type": "array",
"items": {
"type": "string"
}
},
"tableGroupIds": {
"description": "Order of the table groups. Written while a group exists; absent means none",
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"tableEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"logicalName": {
"description": "The name the logical view shows; absent means none",
"type": "string"
},
"comment": {
"type": "string"
},
"columnIds": {
"type": "array",
"items": {
"type": "string"
}
},
"groupId": {
"description": "Id of the table group in doc.tableGroupIds the table belongs to; absent means none",
"type": "string"
},
"nameDerived": {
"description": "The dictionaries filled the name, so a new logical name derives it again; absent means a name someone wrote",
"type": "boolean",
"const": true
},
"ui": {
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"color": {
"type": "string"
}
},
"required": ["x", "y"],
"additionalProperties": false
}
},
"required": ["id", "columnIds", "ui"],
"additionalProperties": false
}
},
"tableColumnEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"tableId": {
"type": "string"
},
"name": {
"type": "string"
},
"comment": {
"type": "string"
},
"dataType": {
"type": "string"
},
"default": {
"type": "string"
},
"options": {
"description": "bit value (autoIncrement: 1) | (primaryKey: 2) | (unique: 4) | (notNull: 8) | (nameDerived: 16); nameDerived is set while the dictionaries filled the name",
"type": "integer"
},
"logicalName": {
"description": "The name the logical view shows; absent means none",
"type": "string"
},
"domainId": {
"description": "Id of the domain in domainEntities that governs the data type; absent means none",
"type": "string"
}
},
"required": ["id", "tableId", "options"],
"additionalProperties": false
}
},
"relationshipEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"relationshipType": {
"description": "bit value (ZeroOne: 2) | (ZeroN: 4) | (OneOnly: 8) | (OneN: 16)",
"type": "integer"
},
"onDelete": {
"description": "bit value (none: 1) | (noAction: 2) | (cascade: 4) | (setNull: 8) | (setDefault: 16) | (restrict: 32); none, the default, writes no ON DELETE clause",
"type": "integer"
},
"onUpdate": {
"description": "bit value (none: 1) | (noAction: 2) | (cascade: 4) | (setNull: 8) | (setDefault: 16) | (restrict: 32); none, the default, writes no ON UPDATE clause",
"type": "integer"
},
"start": {
"$ref": "#/$defs/RelationshipPoint"
},
"end": {
"$ref": "#/$defs/RelationshipPoint"
}
},
"required": [
"id",
"relationshipType",
"onDelete",
"onUpdate",
"start",
"end"
],
"additionalProperties": false
}
},
"indexEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"tableId": {
"type": "string"
},
"indexColumnIds": {
"type": "array",
"items": {
"type": "string"
}
},
"unique": {
"type": "boolean"
}
},
"required": ["id", "tableId", "indexColumnIds", "unique"],
"additionalProperties": false
}
},
"indexColumnEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"indexId": {
"type": "string"
},
"columnId": {
"type": "string"
},
"orderType": {
"description": "bit value (ASC: 1) | (DESC: 2)",
"type": "integer"
}
},
"required": ["id", "indexId", "columnId", "orderType"],
"additionalProperties": false
}
},
"memoEntities": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"type": "string"
},
"ui": {
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"width": {
"type": "number"
},
"height": {
"type": "number"
},
"color": {
"type": "string"
}
},
"required": ["x", "y", "width", "height"],
"additionalProperties": false
}
},
"required": ["id", "ui"],
"additionalProperties": false
}
},
"tableGroupEntities": {
"description": "Named, coloured rectangles drawn behind tables; a table joins one through its groupId. Written while a group exists; absent means none",
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"color": {
"type": "string"
},
"ui": {
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"width": {
"type": "number"
},
"height": {
"type": "number"
}
},
"required": ["x", "y", "width", "height"],
"additionalProperties": false
}
},
"required": ["id", "ui"],
"additionalProperties": false
}
},
"wordEntities": {
"description": "The words of the dictionary, the parts a logical name is composed of, each with its abbreviation in a physical name. Written while a word exists; absent means none",
"type": "object",
"properties": {
"fields": {
"const": ["id", "name", "abbreviation", "englishName", "description", "synonyms", "forbiddenWords"]
},
"rows": {
"description": "One row per entry in document order, its values in the order fields names them; values past the name are left out from the last empty one back",
"type": "array",
"items": {
"type": "array",
"prefixItems": [
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" }
],
"items": false,
"minItems": 2
}
}
},
"required": ["fields", "rows"],
"additionalProperties": false
},
"termEntities": {
"description": "The terms of the dictionary, logical names a column matches by its text, each with its physical name and domain id. Written while a term exists; absent means none",
"type": "object",
"properties": {
"fields": {
"const": ["id", "name", "physicalName", "domainId", "description", "synonyms"]
},
"rows": {
"description": "One row per entry in document order, its values in the order fields names them; values past the name are left out from the last empty one back",
"type": "array",
"items": {
"type": "array",
"prefixItems": [
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" }
],
"items": false,
"minItems": 2
}
}
},
"required": ["fields", "rows"],
"additionalProperties": false
},
"domainEntities": {
"description": "The domains of the dictionary, named data types a column or a term links to by id. Written while a domain exists; absent means none",
"type": "object",
"properties": {
"fields": {
"const": ["id", "name", "category", "dataType", "description"]
},
"rows": {
"description": "One row per entry in document order, its values in the order fields names them; values past the name are left out from the last empty one back",
"type": "array",
"items": {
"type": "array",
"prefixItems": [
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" },
{ "type": "string" }
],
"items": false,
"minItems": 2
}
}
},
"required": ["fields", "rows"],
"additionalProperties": false
},
"RelationshipPoint": {
"type": "object",
"properties": {
"tableId": {
"type": "string"
},
"columnIds": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["tableId", "columnIds"],
"additionalProperties": false
}
}
}