Skip to content

Commit ba7f5a4

Browse files
committed
fix(dbml-to-json): improve multi schema handling
Handle the case where the DBML code include multi schema.
1 parent 1c511f4 commit ba7f5a4

File tree

9 files changed

+85
-23
lines changed

9 files changed

+85
-23
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const DEFAULT_SCHEMA_NAME = "public";
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { DEFAULT_SCHEMA_NAME } from "../constants/schema";
2+
3+
import type Enum from "@dbml/core/types/model_structure/enum";
4+
import type Table from "@dbml/core/types/model_structure/table";
5+
6+
export const computeNameWithSchemaName = (
7+
objectName: string,
8+
schemaName?: string,
9+
): string => {
10+
if (
11+
schemaName !== undefined &&
12+
schemaName !== null &&
13+
schemaName !== DEFAULT_SCHEMA_NAME
14+
) {
15+
return `${schemaName}.${objectName}`;
16+
}
17+
18+
return objectName;
19+
};
20+
21+
export const getTableFullName = (table: Table): string => {
22+
// unfortunately the Table type from dbml package not define the schemaName property
23+
// while it exists
24+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
25+
return computeNameWithSchemaName(table.name, (table as any).schemaName);
26+
};
27+
28+
export const getEnumFullName = (_enum: Enum): string => {
29+
// unfortunately the Enum type from dbml package not define the schemaName property
30+
// while it exists
31+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
32+
return computeNameWithSchemaName(_enum.name, (_enum as any).schemaName);
33+
};

packages/dbml-to-json-table-schema/src/utils/createEnumsSet.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { getEnumFullName } from "./computeNameWithSchemaName";
2+
13
import type Enum from "@dbml/core/types/model_structure/enum";
24

35
export const createEnumsSet = (enums: Enum[]): Set<string> => {
46
const map = new Set<string>();
57

68
enums.forEach((enumObj) => {
7-
map.add(enumObj.name);
9+
map.add(getEnumFullName(enumObj));
810
});
911

1012
return map;
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { type JSONTableEnum } from "shared/types/tableSchema";
22

3+
import { getEnumFullName } from "../computeNameWithSchemaName";
4+
35
import type Enum from "@dbml/core/types/model_structure/enum";
46

5-
export const dbmlEnumToJSONTableEnum = ({
6-
values,
7-
name,
8-
}: Enum): JSONTableEnum => {
7+
export const dbmlEnumToJSONTableEnum = (_enum: Enum): JSONTableEnum => {
98
return {
10-
name,
11-
values: values.map<JSONTableEnum["values"][number]>(({ name, note }) => ({
12-
name,
13-
// the note returned by the dbml parser is not string
14-
// but an object there is an typing error in their package
15-
note: (note as any)?.value,
16-
})),
9+
name: getEnumFullName(_enum),
10+
values: _enum.values.map<JSONTableEnum["values"][number]>(
11+
({ name, note }) => ({
12+
name,
13+
// the note returned by the dbml parser is not string
14+
// but an object there is an typing error in their package
15+
note: (note as any)?.value,
16+
}),
17+
),
1718
};
1819
};

packages/dbml-to-json-table-schema/src/utils/transfomers/dbmlFieldToJSONTableField.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { type JSONTableField } from "shared/types/tableSchema";
22
import { computeRelationalFieldKey } from "shared/utils/computeRelationalFieldKey";
33

4+
import { computeNameWithSchemaName } from "../computeNameWithSchemaName";
5+
46
import type Field from "@dbml/core/types/model_structure/field";
57

68
interface DbmlToJSONTableFieldParams {
@@ -28,6 +30,11 @@ export const dbmlFieldToJSONTableField = ({
2830
const fieldKey = computeRelationalFieldKey(ownerTable, name);
2931

3032
const hasRelation = relationalFieldMap.has(fieldKey);
33+
const typeName = computeNameWithSchemaName(
34+
type.type_name as string,
35+
type.schemaName as string | undefined,
36+
);
37+
3138
return {
3239
name,
3340
pk,
@@ -37,8 +44,8 @@ export const dbmlFieldToJSONTableField = ({
3744
note: (note as any)?.value,
3845
not_null,
3946
type: {
40-
type_name: type.type_name,
41-
is_enum: enumsMap.has(type.type_name as string),
47+
type_name: typeName,
48+
is_enum: enumsMap.has(typeName),
4249
},
4350
is_relation: hasRelation,
4451
relational_tables: hasRelation ? relationalFieldMap.get(fieldKey) : null,
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { type JSONTableRef } from "shared/types/tableSchema";
22

3+
import { computeNameWithSchemaName } from "../computeNameWithSchemaName";
4+
35
import type Endpoint from "@dbml/core/types/model_structure/endpoint";
46

57
export const dbmlRefEndpointToJSONTableRefEndpoint = ({
68
tableName,
79
fieldNames,
810
relation,
11+
schemaName,
912
}: Endpoint): JSONTableRef["endpoints"][number] => {
1013
return {
1114
relation,
12-
tableName,
15+
tableName: computeNameWithSchemaName(tableName, schemaName),
1316
fieldNames,
1417
};
1518
};

packages/dbml-to-json-table-schema/src/utils/transfomers/dbmlTableToJSONTableTable.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { type JSONTableTable } from "shared/types/tableSchema";
22

3+
import { getTableFullName } from "../computeNameWithSchemaName";
4+
35
import { dbmlFieldToJSONTableField } from "./dbmlFieldToJSONTableField";
46
import { dbmlIndexToJSONTableIndex } from "./dbmlIndexToJSONTableIndex";
57

68
import type Table from "@dbml/core/types/model_structure/table";
79

810
export const dbmlTableToJSONTableTable = (
9-
{ name, note, headerColor, fields, indexes }: Table,
11+
table: Table,
1012
relationalFieldMap: Map<string, string[]>,
1113
enumsMap: Set<string>,
1214
): JSONTableTable => {
15+
const { name, note, headerColor, fields, indexes } = table;
16+
1317
return {
14-
name,
18+
name: getTableFullName(table),
1519
headerColor,
1620
// the note returned by the dbml parser is not string
1721
// but an object there is an typing error in their package

packages/dbml-to-json-table-schema/src/validators/validateRefs.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
import { TableNotExistError } from "../errors/TableNotExistError";
22
import { FieldNotExistsError } from "../errors/FieldNotExistsError";
3+
import {
4+
computeNameWithSchemaName,
5+
getTableFullName,
6+
} from "../utils/computeNameWithSchemaName";
37

48
import type Endpoint from "@dbml/core/types/model_structure/endpoint";
59
import type Ref from "@dbml/core/types/model_structure/ref";
610
import type Table from "@dbml/core/types/model_structure/table";
711

8-
912
export const validateRefs = (refs: Ref[], tables: Table[]): void => {
1013
const tableMap = new Map<string, Table>();
1114
tables.forEach((table) => {
12-
tableMap.set(table.name, table);
15+
const tableName = getTableFullName(table);
16+
tableMap.set(tableName, table);
1317
});
1418

1519
refs.forEach((ref) => {
1620
ref.endpoints.forEach((endpoint) => {
17-
if (tableMap.has(endpoint.tableName)) {
21+
const relatedTableFullName = computeNameWithSchemaName(
22+
endpoint.tableName,
23+
endpoint.schemaName,
24+
);
25+
if (tableMap.has(relatedTableFullName)) {
1826
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
19-
validateEndpoint(endpoint, tableMap.get(endpoint.tableName)!);
27+
validateEndpoint(endpoint, tableMap.get(relatedTableFullName)!);
2028
return;
2129
}
2230

23-
throw new TableNotExistError(endpoint.tableName);
31+
throw new TableNotExistError(relatedTableFullName);
2432
});
2533
});
2634
};

packages/shared/types/tableSchema.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ export interface JSONTableIndex
4646
}
4747

4848
export interface JSONTableTable
49-
extends PartialRequired<Pick<Table, "name" | "note" | "headerColor">, "name"> {
49+
extends PartialRequired<
50+
Pick<Table, "name" | "note" | "headerColor">,
51+
"name"
52+
> {
5053
fields: JSONTableField[];
5154
indexes: JSONTableIndex[];
5255
}

0 commit comments

Comments
 (0)