diff --git a/packages/dbml-core/__tests__/examples/model_exporter/dbml_exporter/output/table_group_settings.out.dbml b/packages/dbml-core/__tests__/examples/model_exporter/dbml_exporter/output/table_group_settings.out.dbml index e62c1feaff..d4d7551c61 100644 --- a/packages/dbml-core/__tests__/examples/model_exporter/dbml_exporter/output/table_group_settings.out.dbml +++ b/packages/dbml-core/__tests__/examples/model_exporter/dbml_exporter/output/table_group_settings.out.dbml @@ -1,3 +1,7 @@ +Project "a" { + database_type: '''aaa\'hehe''' +} + Enum "ecommerce"."products_status" { "out_of_stock" "in_stock" diff --git a/packages/dbml-core/__tests__/examples/model_exporter/model_exporter.spec.ts b/packages/dbml-core/__tests__/examples/model_exporter/model_exporter.spec.ts index 81db7f8c6c..4472dc2378 100644 --- a/packages/dbml-core/__tests__/examples/model_exporter/model_exporter.spec.ts +++ b/packages/dbml-core/__tests__/examples/model_exporter/model_exporter.spec.ts @@ -169,6 +169,36 @@ describe('@dbml/core - DbmlExporter flags', () => { }); }); +describe('@dbml/core - DbmlExporter project', () => { + const DBML_WITH_PROJECT = ` +Project "project_name" { + database_type: 'PostgreSQL' + Note: 'Description of the project' +} + +Table "users" { + "id" integer [pk] +}`.trim(); + + test('exports the Project block', () => { + const database = (new Parser()).parse(DBML_WITH_PROJECT, 'dbmlv2'); + const res = DbmlExporter.export(database.normalize(), { includeRecords: true }); + expect(res.trim()).toBe(DBML_WITH_PROJECT); + }); + + test('exports a Project with only a note', () => { + const database = (new Parser()).parse(`Project {\n Note: 'It\\'s a note'\n}`, 'dbmlv2'); + const res = DbmlExporter.export(database.normalize(), { includeRecords: true }); + expect(res.trim()).toBe(`Project {\n Note: '''It\\'s a note'''\n}`); + }); + + test('exports nothing when there is no Project', () => { + const database = (new Parser()).parse('Table "users" {\n "id" integer\n}', 'dbmlv2'); + const res = DbmlExporter.export(database.normalize(), { includeRecords: true }); + expect(res).not.toMatch(/^Project\b/m); + }); +}); + describe('@dbml/core - ModelExporter table groups', () => { test('does not schema-qualify TableGroup names', () => { const database = (new Parser()).parse( diff --git a/packages/dbml-core/src/export/DbmlExporter.ts b/packages/dbml-core/src/export/DbmlExporter.ts index f5085dc525..67d66ad160 100644 --- a/packages/dbml-core/src/export/DbmlExporter.ts +++ b/packages/dbml-core/src/export/DbmlExporter.ts @@ -531,11 +531,25 @@ class DbmlExporter { return blocks.join('\n'); } + static exportProject (model: NormalizedModel): string { + const { name, databaseType, note } = model.database['1']; + if (!name && !databaseType && !note) return ''; + + const projectName = name ? ` "${name}"` : ''; + const databaseTypeStr = databaseType ? ` database_type: ${DbmlExporter.escapeNote(databaseType)}\n` : ''; + const noteStr = note ? ` Note: ${DbmlExporter.escapeNote(note)}\n` : ''; + + return `Project${projectName} {\n${databaseTypeStr}${noteStr}}\n`; + } + static export (model: NormalizedModel, options: DbmlExporterOptions): string { const elementStrs: string[] = []; const database = model.database['1']; const { includeRecords } = options; + const projectStr = DbmlExporter.exportProject(model); + if (projectStr) elementStrs.push(projectStr); + database.schemaIds.forEach((schemaId) => { const { enumIds, tableIds, tableGroupIds, refIds, depIds,