RESOLVES FRMW-2826
**What**
We have many places where we define only one to one on one side of the relation. In that case it is a one to one that does not mapped by to the other side relation since it is not defined. This pr allow to create a one to one without mapped by. In order to remove breaking changes, in that case we ask the user to explicitly define the `mappedBy` as `undefined`
**What**
DML class name and mikro orm entity name are different, it was ok and the idea was to accept that and do the transformation when needed. But since class name are usually upper case first we decided to re integrate that convention in the DML class name as well to simplify consumption of the dml name without having to worry about the normal case
RESOLVES FRMW-2813
**What**
Extract what we have done in the order module DML migration.
This includes all the changes we discussed around default value and nullable management
From now on, when the default is being set through the DML on a property, no default initializer will be created, this means that when a mikro orm class is being instantiated, no default will be applied at instantiation time. This fixes the issue when retrieving data and not selecting fields that have a default. The default initializer was taking the relay making you think the data was present except that it was the value of the default initializer. From now on, the default value is applied as follows
- db column default
- before flush
- on persist
The same applies for nullable properties/columns
Co-authored-by: Harminder Virk <1706381+thetutlage@users.noreply.github.com>
* feat: convert MikroORM entities to DML entities
* feat: wip on repository changes
* continue repositories and types rework
* fix order repository usage
* continue to update product category repository
* Add foreign key as part of the inferred DML type
* ../../core/types/src/dml/index.ts
* ../../core/types/src/dml/index.ts
* fix: relationships mapping
* handle nullable foreign keys types
* handle nullable foreign keys types
* handle nullable foreign keys types
* continue to update product category repository
* fix all product category repositories issues
* fix product category service types
* fix product module service types
* fix product module service types
* fix repository template type
* refactor: use a singleton DMLToMikroORM factory instance
Since the MikroORM MetadataStorage is global, we will also have to turn DML
to MikroORM entities conversion use a global bucket as well
* refactor: update product module to use DML in tests
* wip: tests
* WIP product linkable fixes
* continue type fixing and start test fixing
* test: fix more tests
* fix repository
* fix pivot table computaion + fix mikro orm repository
* fix many to many management and configuration
* fix many to many management and configuration
* fix many to many management and configuration
* update product tag relation configuration
* Introduce experimental dml hooks to fix some issues with categories
* more fixes
* fix product tests
* add missing id prefixes
* fix product category handle management
* test: fix more failing tests
* test: make it all green
* test: fix breaking tests
* fix: build issues
* fix: build issues
* fix: more breaking tests
* refactor: fix issues after merge
* refactor: fix issues after merge
* refactor: surpress types error
* test: fix DML failing tests
* improve many to many inference + tests
* Wip fix columns from product entity
* remove product model before create hook and manage handle validation and transformation at the service level
* test: fix breaking unit tests
* fix: product module service to not update handle on product update
* fix define link and joiner config
* test: fix joiner config test
* test: fix joiner config test
* fix joiner config primary keys
* Fix joiner config builder
* Fix joiner config builder
* test: remove only modifier from test
* refactor: remove hooks usage from product collection
* refactor: remove hooks usage from product-option
* refactor: remove hooks usage for computing category handle
* refactor: remove hooks usage from productCategory model
* refactor: remove hooks from DML
* refactor: remove cruft
* cleanup
* re add foerign key indexes
* chore: remove unused types
* refactor: cleanup
* migration and models configuration adjustments
* cleanup
* fix random ordering
* fix
* test: fix product-category tests
* test: update breaking DML tests
* test: array assertion to not care about ordering
* fix: temporarily apply id ordering for products
* fix ordering
* fix ordering remove logs
---------
Co-authored-by: adrien2p <adrien.deperetti@gmail.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
Initially I thought that we will have to add special checks to allow relationships referencing itself. However, it turned out that not to be the case. Instead, it had more to do with how self relationships are defined in Mikro ORM.
In case of `belongsTo` relationship we have to define the other side as well either as a `hasMany` or `hasOne`. For example:
**❌ The following code will fail, because no children are defined for the parent**
```ts
const user = model.define("user", {
id: model.number(),
username: model.text(),
parent: model.belongsTo(() => user)
})
```
**✅ Addition of children relationship will make things work**
```ts
const user = model.define("user", {
id: model.number(),
username: model.text(),
parent: model.belongsTo(() => user, { mappedBy: "children" }),
children: model.hasMany(() => user, { mappedBy: "parent" }),
})
```
We can see the similar setup here with our `ProductCategory` MikroORM entity. https://github.com/medusajs/medusa/blob/develop/packages/modules/product/src/models/product-category.ts#L87-L94
@adrien2p Correct me if I am wrong. But I have added the tests for now so that we know the behavior of self relationships
**What**
Currently, when setting a `belongsTo` relationship on the DML with the otherside being `hasMany` it result in a wrongly generated gql output making the belongs to being a collection of the relation instead of the relation directly. This pr fixes this issue
**What**
When both sides of a many to many relationship do not define the mapped by option, it leads to misconfigured relations and a malformed SQL query. (ref. https://github.com/medusajs/medusa/issues/9075)
- When both mapped by are not defined, infer look up to try to identify the missing configuration if any
- Disallow defining many to many only on one side
FIXES FRMW-2676
**What**
ref: https://discord.com/channels/876835651130097704/1023889804544458752/threads/1276979858781503528
Currently, when providing the following
```ts
const user1 = manager.create(User, {
username: "User 1",
team: {
name: "Team 1",
},
})
```
It would result in an error inserting into the database because the foreign key will be sent twice as part of the insert, one for the relation and one for the foreign key that both relate to the foreign key property.
To fix that and allow both approaches (providing the entity to cascade persist or just providing the foreign key in case of another side nullable relation) we need to handle it a bit differently.
now both approaches would be valid. the entities for the example might not be the best ones but it is just to illustrate
option 1 - we create both the user and the team:
```ts
const user1 = manager.create(User, {
username: "User 1",
team: {
name: "Team 1",
},
})
```
option 2 - the team already exists (for example the previous user have been detached from the team but we kept the team alive and assign a new user to that team) :
```ts
const user1 = manager.create(User, {
username: "User 1",
team_id: team.id
})
```
**what:**
- DML can apply composite indexes
- Where clause is currently a string, QB version will come as a follow up
```
model.define("user", {
email: model.text(),
account: model.text(),
}).indexes([
{
name: "IDX-unique-name",
unique: true,
on: ["email", "account"],
where: "email is NOT NULL",
},
])
```
RESOLVES CORE-2391
* chore: various DML improvements
* Check is something through static utils
* Check is something through static utils
* allow to define a schema with table name
* restrict searchable to text only
* rm searchable modifier
* extract constructor logic into separate function