mirror of
https://github.com/chartdb/chartdb.git
synced 2025-10-23 07:11:56 +00:00
fix(dbml): fix dbml output format (#815)
This commit is contained in:
@@ -44,6 +44,7 @@ export interface CodeSnippetProps {
|
||||
editorProps?: React.ComponentProps<EditorType>;
|
||||
actions?: CodeSnippetAction[];
|
||||
actionsTooltipSide?: 'top' | 'right' | 'bottom' | 'left';
|
||||
allowCopy?: boolean;
|
||||
}
|
||||
|
||||
export const CodeSnippet: React.FC<CodeSnippetProps> = React.memo(
|
||||
@@ -58,6 +59,7 @@ export const CodeSnippet: React.FC<CodeSnippetProps> = React.memo(
|
||||
editorProps,
|
||||
actions,
|
||||
actionsTooltipSide,
|
||||
allowCopy = true,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const monaco = useMonaco();
|
||||
@@ -131,33 +133,37 @@ export const CodeSnippet: React.FC<CodeSnippetProps> = React.memo(
|
||||
<Suspense fallback={<Spinner />}>
|
||||
{isComplete ? (
|
||||
<div className="absolute right-1 top-1 z-10 flex flex-col gap-1">
|
||||
<Tooltip
|
||||
onOpenChange={setTooltipOpen}
|
||||
open={isCopied || tooltipOpen}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<Button
|
||||
className="h-fit p-1.5"
|
||||
variant="outline"
|
||||
onClick={copyToClipboard}
|
||||
>
|
||||
{isCopied ? (
|
||||
<CopyCheck size={16} />
|
||||
) : (
|
||||
<Copy size={16} />
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side={actionsTooltipSide}>
|
||||
{t(
|
||||
isCopied
|
||||
? 'copied'
|
||||
: 'copy_to_clipboard'
|
||||
)}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{allowCopy ? (
|
||||
<Tooltip
|
||||
onOpenChange={setTooltipOpen}
|
||||
open={isCopied || tooltipOpen}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<span>
|
||||
<Button
|
||||
className="h-fit p-1.5"
|
||||
variant="outline"
|
||||
onClick={copyToClipboard}
|
||||
>
|
||||
{isCopied ? (
|
||||
<CopyCheck size={16} />
|
||||
) : (
|
||||
<Copy size={16} />
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side={actionsTooltipSide}
|
||||
>
|
||||
{t(
|
||||
isCopied
|
||||
? 'copied'
|
||||
: 'copy_to_clipboard'
|
||||
)}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
|
||||
{actions &&
|
||||
actions.length > 0 &&
|
||||
|
@@ -362,9 +362,10 @@ export const exportBaseSQL = ({
|
||||
.join(', ');
|
||||
|
||||
if (fieldNames) {
|
||||
const indexName = table.schema
|
||||
? `${table.schema}_${index.name}`
|
||||
: index.name;
|
||||
const indexName =
|
||||
table.schema && !isDBMLFlow
|
||||
? `${table.schema}_${index.name}`
|
||||
: index.name;
|
||||
sqlScript += `CREATE ${index.unique ? 'UNIQUE ' : ''}INDEX ${indexName} ON ${tableName} (${fieldNames});\n`;
|
||||
}
|
||||
});
|
||||
|
@@ -937,26 +937,24 @@ describe('DBML Export - Issue Fixes', () => {
|
||||
// Check that indexes are properly formatted with names
|
||||
// Note: When a table has a schema, index names are prefixed with the schema
|
||||
expect(result.standardDbml).toContain(
|
||||
'email [unique, name: "public_idx_email"]'
|
||||
'email [unique, name: "idx_email"]'
|
||||
);
|
||||
expect(result.standardDbml).toContain(
|
||||
'created_at [name: "public_idx_created_at"]'
|
||||
'created_at [name: "idx_created_at"]'
|
||||
);
|
||||
expect(result.standardDbml).toContain(
|
||||
'(email, created_at) [name: "public_idx_email_created"]'
|
||||
'(email, created_at) [name: "idx_email_created"]'
|
||||
);
|
||||
|
||||
// Verify proper index syntax in the table
|
||||
const indexSection = result.standardDbml.match(/Indexes \{[\s\S]*?\}/);
|
||||
expect(indexSection).toBeTruthy();
|
||||
expect(indexSection![0]).toContain('email [unique, name: "idx_email"]');
|
||||
expect(indexSection![0]).toContain(
|
||||
'email [unique, name: "public_idx_email"]'
|
||||
'created_at [name: "idx_created_at"]'
|
||||
);
|
||||
expect(indexSection![0]).toContain(
|
||||
'created_at [name: "public_idx_created_at"]'
|
||||
);
|
||||
expect(indexSection![0]).toContain(
|
||||
'(email, created_at) [name: "public_idx_email_created"]'
|
||||
'(email, created_at) [name: "idx_email_created"]'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -350,7 +350,10 @@ const convertToInlineRefs = (dbml: string): string => {
|
||||
// Combine all attributes into a single bracket
|
||||
const combinedAttributes = allAttributes.join(', ');
|
||||
|
||||
return `${fieldPart.trim()} [${combinedAttributes}]${commentPart || ''}`;
|
||||
// Preserve original spacing from fieldPart
|
||||
const leadingSpaces = fieldPart.match(/^(\s*)/)?.[1] || '';
|
||||
const fieldDefWithoutSpaces = fieldPart.trim();
|
||||
return `${leadingSpaces}${fieldDefWithoutSpaces} [${combinedAttributes}]${commentPart || ''}`;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -388,7 +391,10 @@ const convertToInlineRefs = (dbml: string): string => {
|
||||
.filter((line) => !line.trim().startsWith('Ref '));
|
||||
const finalDbml = finalLines.join('\n').trim();
|
||||
|
||||
return finalDbml;
|
||||
// Clean up excessive empty lines - replace multiple consecutive empty lines with just one
|
||||
const cleanedDbml = finalDbml.replace(/\n\s*\n\s*\n/g, '\n\n');
|
||||
|
||||
return cleanedDbml;
|
||||
};
|
||||
|
||||
// Function to check for SQL keywords (add more if needed)
|
||||
@@ -804,9 +810,15 @@ export function generateDBMLFromDiagram(diagram: Diagram): DBMLExportResult {
|
||||
standard = restoreTableSchemas(standard, diagram);
|
||||
|
||||
// Prepend Enum DBML to the standard output
|
||||
standard = enumsDBML + '\n' + standard;
|
||||
if (enumsDBML) {
|
||||
standard = enumsDBML + '\n\n' + standard;
|
||||
}
|
||||
|
||||
inline = normalizeCharTypeFormat(convertToInlineRefs(standard));
|
||||
|
||||
// Clean up excessive empty lines in both outputs
|
||||
standard = standard.replace(/\n\s*\n\s*\n/g, '\n\n');
|
||||
inline = inline.replace(/\n\s*\n\s*\n/g, '\n\n');
|
||||
} catch (error: unknown) {
|
||||
console.error(
|
||||
'Error during DBML generation process:',
|
||||
@@ -822,11 +834,11 @@ export function generateDBMLFromDiagram(diagram: Diagram): DBMLExportResult {
|
||||
|
||||
// If an error occurred, still prepend enums if they exist, or they'll be lost.
|
||||
// The error message will then follow.
|
||||
if (standard.startsWith('// Error generating DBML:')) {
|
||||
standard = enumsDBML + standard;
|
||||
if (standard.startsWith('// Error generating DBML:') && enumsDBML) {
|
||||
standard = enumsDBML + '\n\n' + standard;
|
||||
}
|
||||
if (inline.startsWith('// Error generating DBML:')) {
|
||||
inline = enumsDBML + inline;
|
||||
if (inline.startsWith('// Error generating DBML:') && enumsDBML) {
|
||||
inline = enumsDBML + '\n\n' + inline;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user