chore(fulfillment, utils): Migrate module to DML (#10617)
**What**
- Allow to provide `foreignKeyName` option for hasOne and belongsTo relationships
- `model.hasOne(() => OtherEntity, { foreignKey: true, foreignKeyName: 'other_entity_something_id' })`
- The above will also output a generated type that takes into consideration the custom fk name 🔽
- Update types to account for defined custom foreign key name
- Fix joiner config linkable generation to account for custom linkable keys that provide a public API for their model but are not part of the list of the models included in the MedusaService
- This was supposed to be handled correctly but the implementation was not considering that custom linkable keys could reference models not part of the one provided to medusa service
- Migrate fulfillment module to DML
- Fix has one with fk behaviour and hooks (the relation should be assigned but not the fk)
- Fix has one belongsTo hooks (the relation should be assigned but not the fk)
- Fix hasOneWithFk and belongsTo non persisted fk to be selectable
- Allow to define `belongsTo` without other side definition for `ManyToOne` with no counter part defined
- Meaning that if a user defined `belongsTo` on one side andnot mapped by and no counter part on the other entity it will be considered as a `ManyToOne`
- `orphanRemoval` on `OneToOne` have been removed, this means that when assigning a new object relation to an entity, the previous one gets deconected but not deleted automatically. This prevent removing data un volountarely
**NOTE**
As per our convention here are some information to keep in mind
**HasOne <> BelongsTo**
Define `OneToOne`, The foreign key is owned by the belongs to and the relation needs to be provided to cascade if wanted
**HasMany <> BelongsTo**
Define `OneToMane` <> `ManyToOne`, the foreign key is owned by the many to one and for those relation no cascade will be performed, the foreign key must be provided. For the `HasMany` the cascade is available
**HasOne (with FK)**
Will act similarly to belongs to with **HasOne <> BelongsTo**
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
65007c49f6
commit
100da64242
@@ -613,10 +613,15 @@ describe("joiner-config-builder", () => {
|
||||
}
|
||||
)
|
||||
|
||||
const linkConfig = buildLinkConfigFromModelObjects("myService", {
|
||||
user,
|
||||
car,
|
||||
})
|
||||
const linkableKeysFromDml = buildLinkableKeysFromDmlObjects([user, car])
|
||||
const linkConfig = buildLinkConfigFromModelObjects(
|
||||
"myService",
|
||||
{
|
||||
user,
|
||||
car,
|
||||
},
|
||||
linkableKeysFromDml
|
||||
)
|
||||
|
||||
expectTypeOf(linkConfig).toMatchTypeOf<{
|
||||
user: {
|
||||
|
||||
@@ -413,41 +413,41 @@ export function buildLinkConfigFromModelObjects<
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the joiner config specify some custom linkable keys, we merge them with the
|
||||
* existing linkable keys infered from the model above.
|
||||
*/
|
||||
const linkableKeysPerModel = Object.entries(linkableKeys).reduce(
|
||||
(acc, [key, entityName]) => {
|
||||
acc[entityName] ??= []
|
||||
acc[entityName].push(key)
|
||||
return acc
|
||||
},
|
||||
{}
|
||||
/**
|
||||
* If the joiner config specify some custom linkable keys, we merge them with the
|
||||
* existing linkable keys infered from the model above.
|
||||
*/
|
||||
for (const [linkableKey, modelName] of Object.entries(linkableKeys) ?? []) {
|
||||
const snakeCasedModelName = camelToSnakeCase(toCamelCase(modelName))
|
||||
|
||||
// Linkable keys by default are prepared with snake cased model name _id
|
||||
// So to be able to compare only the property we have to remove the first part
|
||||
const inferredReferenceProperty = linkableKey.replace(
|
||||
`${snakeCasedModelName}_`,
|
||||
""
|
||||
)
|
||||
|
||||
for (const linkableKey of linkableKeysPerModel[classLikeModelName] ?? []) {
|
||||
const snakeCasedModelName = camelToSnakeCase(toCamelCase(model.name))
|
||||
linkConfig[lowerCaseFirst(modelName)] ??= {
|
||||
toJSON: function () {
|
||||
const linkables = Object.entries(this)
|
||||
.filter(([name]) => name !== "toJSON")
|
||||
.map(([, object]) => object)
|
||||
return linkables[0]
|
||||
},
|
||||
}
|
||||
|
||||
// Linkable keys by default are prepared with snake cased model name _id
|
||||
// So to be able to compare only the property we have to remove the first part
|
||||
const inferredReferenceProperty = linkableKey.replace(
|
||||
`${snakeCasedModelName}_`,
|
||||
""
|
||||
)
|
||||
if (linkConfig[lowerCaseFirst(modelName)][inferredReferenceProperty]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (modelLinkConfig[inferredReferenceProperty]) {
|
||||
continue
|
||||
}
|
||||
|
||||
modelLinkConfig[linkableKey] = {
|
||||
linkable: linkableKey,
|
||||
primaryKey: linkableKey,
|
||||
serviceName,
|
||||
field: lowerCaseFirst(model.name),
|
||||
entity: upperCaseFirst(model.name),
|
||||
}
|
||||
linkConfig[lowerCaseFirst(modelName)][inferredReferenceProperty] = {
|
||||
linkable: linkableKey,
|
||||
primaryKey: inferredReferenceProperty,
|
||||
serviceName,
|
||||
field: lowerCaseFirst(modelName),
|
||||
entity: upperCaseFirst(modelName),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user