-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sample recreation of issue in memory
- Loading branch information
1 parent
df74290
commit 5020a5a
Showing
7 changed files
with
195 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Entity, ManyToOne, OneToMany, Collection, ManyToMany, PrimaryKeyProp } from "@mikro-orm/core"; | ||
import { Account } from "./account.entity"; | ||
import { Project } from "./project.entity"; | ||
import { User } from "./user.entity"; | ||
import { Document } from "./document.entity"; | ||
|
||
|
||
@Entity({ | ||
tableName: 'accounts_users', | ||
}) | ||
export class AccountUser { | ||
@ManyToOne({ entity: () => Account, primary: true }) | ||
account: Account; | ||
|
||
@ManyToOne({ entity: () => User, primary: true, updateRule: 'cascade' }) | ||
user: User; | ||
|
||
@OneToMany(() => Document, (document) => document.assignee) | ||
assignedDocuments = new Collection<Document>(this); | ||
|
||
@ManyToMany(() => Project, (project) => project.assignedUsers) | ||
assignedProjects = new Collection<Project>(this); | ||
|
||
[PrimaryKeyProp]?: ['account', 'user']; // this is needed for proper type checks in `FilterQuery` | ||
|
||
constructor(account: Account, user: User) { | ||
this.account = account; | ||
this.user = user; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Entity, PrimaryKey, ManyToMany, Collection, OneToMany } from "@mikro-orm/core"; | ||
import { v4 } from "uuid"; | ||
import { AccountUser } from "./account-user.entity"; | ||
import { Project } from "./project.entity"; | ||
import { User } from "./user.entity"; | ||
|
||
@Entity() | ||
export class Account { | ||
@PrimaryKey({ unique: true }) | ||
id: string = v4(); | ||
|
||
// An Org has users so owner | ||
@ManyToMany({ | ||
entity: () => User, | ||
pivotEntity: () => AccountUser, | ||
type: User, | ||
}) | ||
users = new Collection<User>(this); | ||
|
||
@OneToMany(() => Project, (project) => project.account) | ||
projects = new Collection<Project>(this); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Entity, PrimaryKey, ManyToOne } from "@mikro-orm/core"; | ||
import { v4 } from "uuid"; | ||
import { AccountUser } from "./account-user.entity"; | ||
import { Account } from "./account.entity"; | ||
import { Project } from "./project.entity"; | ||
|
||
@Entity({ | ||
tableName: 'documents', | ||
}) | ||
export class Document { | ||
@PrimaryKey({ unique: true }) | ||
id: string = v4(); | ||
|
||
@ManyToOne(() => Project, { index: true }) | ||
project!: Project; | ||
|
||
@ManyToOne(() => Account, { hidden: true, index: true }) | ||
account!: Account; | ||
|
||
@ManyToOne(() => AccountUser, { nullable: true }) | ||
assignee!: AccountUser; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Entity, PrimaryKey, Property, ManyToOne, OneToMany, Collection, ManyToMany } from "@mikro-orm/core"; | ||
import { v4 } from "uuid"; | ||
import { AccountUser } from "./account-user.entity"; | ||
import { Account } from "./account.entity"; | ||
import { Document } from "./document.entity"; | ||
|
||
@Entity({ | ||
tableName: 'projects', | ||
}) | ||
export class Project { | ||
@PrimaryKey({ unique: true }) | ||
id: string = v4(); | ||
|
||
@Property() | ||
name!: string; | ||
|
||
@ManyToOne(() => Account, { nullable: true, hidden: true, index: true }) | ||
account?: Account; | ||
|
||
@OneToMany(() => Document, (document) => document.project) | ||
documents = new Collection<Document>(this); | ||
|
||
@ManyToMany(() => AccountUser, 'assignedProjects', { owner: true }) | ||
assignedUsers = new Collection<AccountUser>(this); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Entity, PrimaryKey, Property, ManyToMany, Collection } from "@mikro-orm/core"; | ||
import { v4 } from "uuid"; | ||
import { Account } from "./account.entity"; | ||
|
||
@Entity() | ||
export class User { | ||
|
||
@PrimaryKey({ unique: true }) | ||
id: string = v4(); | ||
|
||
@Property({ unique: true }) | ||
email!: string; | ||
|
||
@ManyToMany({ entity: () => Account, mappedBy: (o) => o.users }) | ||
accounts = new Collection<Account>(this); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,87 @@ | ||
import { Entity, MikroORM, PrimaryKey, Property } from '@mikro-orm/sqlite'; | ||
import { AccountUser } from './entities/account-user.entity'; | ||
import { Account } from './entities/account.entity'; | ||
import { Project } from './entities/project.entity'; | ||
import { User } from './entities/user.entity'; | ||
import { Document } from './entities/document.entity'; | ||
import { MikroORM } from '@mikro-orm/sqlite'; | ||
|
||
@Entity() | ||
class User { | ||
|
||
@PrimaryKey() | ||
id!: number; | ||
|
||
@Property() | ||
name: string; | ||
|
||
@Property({ unique: true }) | ||
email: string; | ||
|
||
constructor(name: string, email: string) { | ||
this.name = name; | ||
this.email = email; | ||
} | ||
|
||
} | ||
|
||
let orm: MikroORM; | ||
|
||
beforeAll(async () => { | ||
orm = await MikroORM.init({ | ||
dbName: ':memory:', | ||
entities: [User], | ||
entities: [User, Account, AccountUser, Project, Document], | ||
debug: ['query', 'query-params'], | ||
allowGlobalContext: true, // only for testing | ||
}); | ||
await orm.schema.refreshDatabase(); | ||
}); | ||
|
||
|
||
afterAll(async () => { | ||
await orm.close(true); | ||
}); | ||
|
||
test('basic CRUD example', async () => { | ||
orm.em.create(User, { name: 'Foo', email: 'foo' }); | ||
await orm.em.flush(); | ||
orm.em.clear(); | ||
|
||
const user = await orm.em.findOneOrFail(User, { email: 'foo' }); | ||
expect(user.name).toBe('Foo'); | ||
user.name = 'Bar'; | ||
orm.em.remove(user); | ||
await orm.em.flush(); | ||
// Doing this in a pattern to simulate our api calls | ||
// Create a new account and a user that belongs to account | ||
// This is a many to many relationship as a user can belong to multiple accounts | ||
const account = new Account(); | ||
const user = new User(); | ||
user.email = '[email protected]'; | ||
account.users.add(user); | ||
await orm.em.persistAndFlush(account); | ||
|
||
|
||
const count = await orm.em.count(User, { email: 'foo' }); | ||
expect(count).toBe(0); | ||
|
||
// Create a quick sample project and assign the user to it | ||
const project1 = new Project(); | ||
project1.name = 'My First Project'; | ||
const foundUser = await orm.em.findOneOrFail(User, { | ||
email: '[email protected]', | ||
}); | ||
const accountUser = await orm.em.findOne(AccountUser, { | ||
user: foundUser, | ||
}); | ||
if(!accountUser){ | ||
return; | ||
} | ||
project1.assignedUsers.add(accountUser); | ||
await orm.em.persistAndFlush(project1); | ||
|
||
// This breads below, refetching the user to simulate this being a new request | ||
// and even clearing the cache | ||
orm.em.clear(); | ||
const document = new Document(); | ||
const document1 = new Document(); | ||
document.account = account; | ||
document1.account = account; | ||
const project = await orm.em.findOne(Project, { | ||
name: 'My First Project', | ||
}); | ||
if(!project){ | ||
return; | ||
} | ||
const broken_user = await orm.em.findOneOrFail(User, { | ||
email: '[email protected]', | ||
}); | ||
const broken_account_user = await orm.em.findOne( | ||
AccountUser, | ||
{ | ||
user: broken_user, | ||
}, | ||
{ | ||
// Spefically populating the relation causes this blow up of "assigned Projects" | ||
populate: ['assignedProjects', 'assignedDocuments'], | ||
}, | ||
); | ||
if(!broken_account_user){ | ||
return; | ||
} | ||
document.assignee = broken_account_user; | ||
document1.assignee = broken_account_user; | ||
project.documents.add(document); | ||
project.documents.add(document1); | ||
await orm.em.persistAndFlush(project); | ||
}); |