Skip to content

Commit 61043da

Browse files
fix: prioritise foreign keys over primary keys in pg-schema-print-types (#250)
If a key was both a foreign key and a primary key, we would incorrectly generate a branded type for it, rather than referencing the column being referenced by the foreign key.
1 parent 97938d4 commit 61043da

File tree

1 file changed

+31
-28
lines changed

1 file changed

+31
-28
lines changed

packages/pg-schema-print-types/src/printers/printClassDetails.ts

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -119,38 +119,41 @@ function getAttributeType(
119119
return columnTypeOverride;
120120
}
121121

122-
for (const constraint of type.constraints) {
123-
if (constraint.tableAttributeNumbers.includes(attribute.attributeNumber)) {
124-
if (
125-
constraint.constraintType === ConstraintType.ForeignKey &&
126-
constraint.referencedClassID !== type.classID
127-
) {
128-
const referencedClass = context.getClass(constraint.referencedClassID);
129-
if (referencedClass) {
130-
const referencedAttributeNumber =
131-
constraint.referencedAttributeNumbers[
132-
constraint.tableAttributeNumbers.indexOf(
133-
attribute.attributeNumber,
134-
)
135-
];
136-
const referencedAttribute = referencedClass.attributes.find(
137-
(a) => a.attributeNumber === referencedAttributeNumber,
138-
);
139-
if (referencedAttribute) {
140-
const {DatabaseRecord} = printClassDetails(
141-
referencedClass,
142-
context,
143-
);
144-
return `${file.getImport(DatabaseRecord)}['${
145-
referencedAttribute.attributeName
146-
}']`;
147-
}
122+
const constraints = type.constraints.filter((c) =>
123+
c.tableAttributeNumbers.includes(attribute.attributeNumber),
124+
);
125+
// First check if this attribute is a foreign key. If it is, write the type
126+
// as a reference to that other table's attribute
127+
for (const constraint of constraints) {
128+
if (
129+
constraint.constraintType === ConstraintType.ForeignKey &&
130+
constraint.referencedClassID !== type.classID
131+
) {
132+
const referencedClass = context.getClass(constraint.referencedClassID);
133+
if (referencedClass) {
134+
const referencedAttributeNumber =
135+
constraint.referencedAttributeNumbers[
136+
constraint.tableAttributeNumbers.indexOf(attribute.attributeNumber)
137+
];
138+
const referencedAttribute = referencedClass.attributes.find(
139+
(a) => a.attributeNumber === referencedAttributeNumber,
140+
);
141+
if (referencedAttribute) {
142+
const {DatabaseRecord} = printClassDetails(referencedClass, context);
143+
return `${file.getImport(DatabaseRecord)}['${
144+
referencedAttribute.attributeName
145+
}']`;
148146
}
149-
} else if (constraint.constraintType === ConstraintType.PrimaryKey) {
150-
return handleBrand(type.className, attribute, context, file);
151147
}
152148
}
153149
}
150+
// If it's not a foreign key, check if it's a primary key.
151+
// If it is a primary key, we may want to use a branded type.
152+
for (const constraint of constraints) {
153+
if (constraint.constraintType === ConstraintType.PrimaryKey) {
154+
return handleBrand(type.className, attribute, context, file);
155+
}
156+
}
154157
return context.getTypeScriptType(attribute.typeID, file);
155158
}
156159

0 commit comments

Comments
 (0)