Executing Functions After Object Creation
If you want to execute a function after creating an object, use .after
. The first argument is the created object, and the second argument is the variables.
import { factory } from "@factory-js/factory";
import { db } from "./db";
const userFactory = factory
.define(
{
props: {
name: () => "John",
},
vars: {
greeting: () => "Hello",
},
},
async (user) => {
return db.user.create({ data: user });
},
)
.after((user, vars) => {
console.log(user, vars.greeting);
});
await userFactory.create(); // 👉 Logs { name: "John" }, Hello to the console
⚠️
.after
is only executed when .create
is called. It is not executed when
creating objects with .build
.
You can also add multiple hooks in a method chain.
await userFactory
.after(() => console.log(1))
.after(() => console.log(2))
.after(() => console.log(3))
.create(); // 👉 Logs 1 2 3 to the console
Creating One-to-Many Relationships
A useful case for .after
is when you want to generate objects with one-to-many relationships, such as when using an ORM. In the example below, a user with three posts is created in a single .create
call.
import { factory, later } from "@factory-js/factory";
// Define the user factory
const userFactory = factory.define(
{
props: {
id: () => 1,
},
vars: {},
},
async (user) => {
return db.user.create({ data: user });
},
);
// Define the post factory
const postFactory = factory
.define(
{
props: {
userId: later<string>(),
title: () => "title",
},
vars: {
user: () => await userFactory.create(),
},
},
async (profile) => {
return db.profile.create({ data: profile });
},
)
.props({
userId: async ({ vars }) => (await vars.user).id,
});
// Generate a user with three posts and save them to the database
await userFactory
.after((user) => postFactory.vars({ user: () => user }).createList(3))
.create();
In practice, rather than using .after
on its own, it is more convenient to
use it in combination with .traits
. For more details, refer to
Trait.