Entity Cloning
Joist supports cloning entities, to easily implement feature requests like “duplicate this author”, or “duplicate this author and all of their books”.
To clone an entity, call em.clone and pass a load-hint of the subgraph you want to be included in the clone operation.
For example, to clone an Author plus all of their Books and all of the Book’s BookReviews, you can call:
const a1 = await em.load(Author, "a:1");const a2 = await em.clone(a1, { books: "reviews" })After the em.clone is finished:
a2will be a copy ofa1with all the same primitive field values, but a new primary key/new identity- Each
Bookina1.bookswill have a newBookinstance created, and be correctly hooked up toa2instead of the originala1 - Each
BookReviewin eacha1.books.reviewswill have a newBookReviewinstance created, and again be correctly up to the right newly-createdBookinstance ina2.books
Besides setting the correct “parent” book.author to a2 for each cloned child Book, any other references/FKs in the newly-created entities that happened to point to also-cloned input entities (like a1.favoriteBook pointing to a1.books.get[0]) are adjusted to point to the correct/corresponding newly-cloned output entity.
Basically Joist will keep the subgraph of cloned entities intact.
Advanced Features
Section titled “Advanced Features”When calling em.clone, you can provide three config options to customize the behavior:
-
opts.deepis the load hint from above, i.e.{ books: "reviews" }, that specifies the subgraph to clone. -
opts.skipIfis a function that accepts an entity and returnstrueif that entity should be skipped/not cloned:// This will duplicate the author's books, but skip any book where the title includes `sea`const duplicatedBooks = await em.clone(author.books.get,{ skipIf: (original) => original.title.includes("sea") }); -
opts.postCloneis a function that accepts both the original entity and its new clone, to allow customizing to the clone:// This will duplicate the author's books, and assign them to a different authorconst duplicatedBooks = await em.clone(author.books.get,{ postClone: (_original, clone) => clone.author.set(author2) });