Repository: Quramy/prisma-fabbrica
Pull request #285 (2024-03-12 05:55:22)

Next version(2.2.0)
Planning version: v2.2.0 ( try it `npm i @quramy/prisma-fabbrica@next` )

---

## New Features

- Transient fields (#326)
- Callback functions (#254)
- Improve `createList` signature (#335)

### Transient fields

Transient fields allows to define arbitrary parameters to factories.

```ts
const UserFactory = defineUserFactory.withTransientFields({
  loginCount: 0,
})({
  defaultData: async ({ loginCount }) => ({
    /* Do something using `loginCount` parameter */
  }),
});

await UserFactory.create({
  name: "Bob", // `name` field is defined in scehma.primsma
  loginCount: 100, // `loginCount` field is NOT defined in schema but defined in factory
});
```

If you want more details, See [docs](https://github.com/Quramy/prisma-fabbrica/tree/main#transient-fields)

### Callback functions

Allow to define callback functions when to define factories like this:

```ts
const UserFactory = defineUserFactory({
  onAfterCreate: async (user) => {
    await PostFactory.craete({
      author: { connect: uesr },
    });
  },
});

await UserFactory.create();
```

Available callback functions are `onAfterBuild`, `onBeforeCreate`, and `onAfterCreate`.

If you want more details, See [docs](https://github.com/Quramy/prisma-fabbrica/tree/main#callbacks)

### Improve `createList` signature

`createList` (or `buildList`) method in factory interface accepts the 2nd argument.
The 2nd argument can be an object assignable to `Partial<Prisma.MODEL.CreateInput>`.

```ts
// Insert 10 LoginHistory model records with the same `userId` field.
await LoginHistoryFactory.createList(10, { userId: "user001" });
```



Patch:
diff --git a/README.md b/README.md
index 82ebeec..bf61096 100644
--- a/README.md
+++ b/README.md
@@ -21,12 +21,15 @@ Prisma generator for model factories.
   - [has-many / has-one relation](#has-many--has-one-relation)
   - [Custom scalar field generation](#custom-scalar-field-generation)
   - [Traits](#traits)
+  - [Callbacks](#callbacks)
+  - [Transient fields](#transient-fields)
   - [Field value precedence](#field-value-precedence)
   - [More examples](#more-examples)
 - [Generator configuration](#generator-configuration)
 - [Tips](#tips)
   - [Works with jest-prisma](#works-with-jest-prisma)
   - [Suppress TS circular dependencies error](#suppress-ts-circular-dependencies-error)
+  - [Factory interface with types](#factory-interface-with-types)
 - [Version compatibility](#version-compatibility)
 - [License](#license)
 
@@ -91,7 +94,8 @@ async function seed() {
 seed();
 ```
 
-Note: The factories use Prisma client instance passed by `initialize` function.
+> [!NOTE]
+> The factories use Prisma client instance passed by `initialize` function.
 
 If you want to use factories in your test code see [Works with jest-prisma](#works-with-jest-prisma) section below.
 
@@ -122,7 +126,8 @@ await UserFactory.create(); // Insert record with auto filled id, email, firstNa
 
 See https://github.com/Quramy/prisma-fabbrica/blob/main/packages/prisma-fabbrica/src/scalar/gen.ts if you want auto filling rule details.
 
-Note: prisma-fabbrica auto filling does not affect fields with `@default()` function.
+> [!NOTE]
+> prisma-fabbrica auto filling does not affect fields with `@default()` function.
 
 Default filling rule also can be overwritten.
 
@@ -174,6 +179,12 @@ await UserFactory.createList(3);
 await Promise.all([0, 1, 2].map(() => UserFactory.create()));
 ```
 
+The 2nd argument(optional) accepts an object which is assignable to `Partial<Prisma.UserCreateInput>` :
+
+```ts
+await UserFactory.createList(3, { name: "Bob" });
+```
+
 You can also pass list data assignable to `Partial<Prisma.UserCreateInput>[]` :
 
 ```ts
@@ -309,7 +320,8 @@ await UserFactory.create({
 console.log(await prisma.post.count()); // -> 2
 ```
 
-Note: In the above example, `PostFactory.build()` resolves JSON data such as:
+> [!NOTE]
+> In the above example, `PostFactory.build()` resolves JSON data such as:
 
 ```ts
 {
@@ -375,6 +387,106 @@ Multiple traits are also available:
 await UserFactory.use("someTrait", "anotherTrait").create();
 ```
 
+### Callbacks
+
+You can set callback function before or after factory execution.
+
+```ts
+const UserFactory = defineUserFactory({
+  onAfterCreate: async user => {
+    await PostFactory.craete({
+      author: { connect: uesr },
+    });
+  },
+});
+
+await UserFactory.create();
+```
+
+Callback functions are also available within trait definition.
+
+```ts
+const UserFactory = defineUserFactory({
+  traits: {
+    withComment: {
+      onAfterCreate: async user => {
+        await PostFactory.craete({
+          author: { connect: uesr },
+        });
+      },
+    },
+  },
+});
+
+await UserFactory.create();
+await UserFactory.use("withComment").create();
+```
+
+> [!NOTE]
+> The above code is to explain the callback. If you want to create association, first consider to use `defaultData` and `trait.data` option as in [has-many / has-one relation](#has-many--has-one-relation).
+
+The following three types are available as callback function:
+
+```ts
+const UserFactory = defineUserFactory({
+  onAfterBuild: async createInput => {
+    // do something
+  },
+  onBeforeCreate: async createInput => {
+    // do something
+  },
+  onAfterCreate: async createdData => {
+    // do something
+  },
+});
+```
+
+And here, the parameter types are:
+
+- `createInput` is assignable to model create function parameter (e.g. `Prsima.UserCreateInput`).
+- `createdData` is resolved object by model create function (e.g. `User` model type)
+
+### Transient fields
+
+Transient fields allow to define arbitrary parameters to factory and to pass them when calling `create` or `build`.
+
+```ts
+const UserFactory = defineUserFactory.withTransientFields({
+  loginCount: 0, // `0` is default value of this parameter
+})({
+  defaultData: async ({ loginCount }) => {
+    // using loginCount
+  },
+});
+
+await UserFactory.create({ name: "Bob", loginCount: 10 });
+```
+
+Transient fields passed from factories' `create` method don't affect Prisma's `create` result.
+
+> [!NOTE]
+> You can't use model field names defined in your schema.prisma as transient parameters because they're not passed to `prisma.user.create` method.
+
+Transient fields also can be accessed from [traits](#traits) or [callbacks](#callbacks).
+
+```ts
+const UserFactory = defineUserFactory.withTransientFields({
+  loginCount: 0,
+})({
+  // Transient fields are passed to callback functions as the 2nd argument.
+  onAfterCreate: async (createdUser, { loginCount }) => {
+    for (let i = 0; i < loginCount; i++) {
+      await writeLoginLog(craetedUser.id);
+    }
+  },
+  traits: {
+    data: async ({ loginCount }) => {
+      // using loginCount
+    },
+  },
+});
+```
+
 ### Field value precedence
 
 Each field is determined in the following priority order(lower numbers have higher priority):
@@ -448,7 +560,7 @@ const PostFactory = definePostFactory({
 });
 ```
 
-`FactoryInterface` types are available to avoid this error.
+`FactoryInterface` types are available to avoid this error. See [Factory interface with types](#factory-interface-with-types) section if you want usage of factory interface.
 
 ```ts
 import { defineUserFactory, definePostFactory, type UserFactoryInterface } from "./__generated__/fabbrica";
@@ -472,6 +584,39 @@ const PostFactory = definePostFactory({
 });
 ```
 
+### Factory interface with types
+
+> [!WARNING]
+> Factory interface type parameters may change in future versions without notice.
+
+Factory interface (e.g. `UserFactory` ) takes 2 optional type parameters:
+
+- `TTransientFields`: Type of [transient fields](#transient-fields) object. By default, `Record<string, unknown>` .
+- `TTraitName`: Names of available [traits](#traits). By default, `string | symbol` .
+
+For example:
+
+```ts
+// Specify transient fields type
+declare function getUserFactory(): UserFactoryInterface<{ loginCount: number }>;
+
+await getUserFactory().create({ loginCount: 10 });
+
+// @ts-expect-error
+await getUserFactory().create({ hoge: 10 });
+```
+
+```ts
+// Specify available trait names
+declare function getUserFactory(): UserFactoryInterface<{}, "someTrait" | "anotherTrait">;
+
+await getUserFactory().use("someTrait").create();
+await getUserFactory().use("anotherTrait").create();
+
+// @ts-expect-error
+await getUserFactory().use("hoge").create();
+```
+
 ## Version compatibility
 
 - **If your @prisma/client's version >= 5.0.0, install `@quramy/prisma-fabbrica@2.x.x`.**
diff --git a/examples/example-prj/package.json b/examples/example-prj/package.json
index d1f34c8..8a1af56 100644
--- a/examples/example-prj/package.json
+++ b/examples/example-prj/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "example-prj",
-  "version": "2.1.5",
+  "version": "2.2.0-alpha.4",
   "scripts": {
     "bootstrap": "npm run generate",
     "clean": "echo nothing to do",
diff --git a/examples/example-prj/prisma/migrations/20240613173903_add_login_log/migration.sql b/examples/example-prj/prisma/migrations/20240613173903_add_login_log/migration.sql
new file mode 100644
index 0000000..4c3a29c
--- /dev/null
+++ b/examples/example-prj/prisma/migrations/20240613173903_add_login_log/migration.sql
@@ -0,0 +1,7 @@
+-- CreateTable
+CREATE TABLE "LoginLog" (
+    "id" TEXT NOT NULL PRIMARY KEY,
+    "userId" TEXT NOT NULL,
+    "clientId" TEXT NOT NULL,
+    "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
diff --git a/examples/example-prj/prisma/schema.prisma b/examples/example-prj/prisma/schema.prisma
index 1c76332..c461cb5 100644
--- a/examples/example-prj/prisma/schema.prisma
+++ b/examples/example-prj/prisma/schema.prisma
@@ -21,6 +21,13 @@ model User {
   createdAt DateTime  @default(now())
 }
 
+model LoginLog {
+  id        String @id @default(cuid())
+  userId    String
+  clientId  String
+  createdAt DateTime @default(now())
+}
+
 model Post {
   id         String     @id
   title      String
diff --git a/examples/example-prj/src/__generated__/fabbrica/index.d.ts b/examples/example-prj/src/__generated__/fabbrica/index.d.ts
index de0c7fa..fce8999 100644
--- a/examples/example-prj/src/__generated__/fabbrica/index.d.ts
+++ b/examples/example-prj/src/__generated__/fabbrica/index.d.ts
@@ -1,12 +1,19 @@
 import type { User } from "@prisma/client";
+import type { LoginLog } from "@prisma/client";
 import type { Post } from "@prisma/client";
 import type { Comment } from "@prisma/client";
 import type { Category } from "@prisma/client";
 import type { Prisma } from "@prisma/client";
 import type { Resolver } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+type TraitName = string | symbol;
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 export declare const initialize: (options: import("@quramy/prisma-fabbrica/lib/initialize").InitializeOptions) => void;
 type UserFactoryDefineInput = {
@@ -18,27 +25,35 @@ type UserFactoryDefineInput = {
     posts?: Prisma.PostCreateNestedManyWithoutAuthorInput;
     comments?: Prisma.CommentCreateNestedManyWithoutAuthorInput;
 };
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
-export interface UserFactoryInterfaceWithoutTraits {
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
+}
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
 }
 /**
  * Define factory for {@link User} model.
@@ -46,7 +61,50 @@ export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export declare function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions>;
+export declare const defineUserFactory: UserFactoryBuilder;
+type LoginLogFactoryDefineInput = {
+    id?: string;
+    userId?: string;
+    clientId?: string;
+    createdAt?: Date;
+};
+type LoginLogTransientFields = Record<string, unknown> & Partial<Record<keyof LoginLogFactoryDefineInput, never>>;
+type LoginLogFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<LoginLogFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<LoginLog, Prisma.LoginLogCreateInput, TTransients>;
+type LoginLogFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<LoginLogFactoryDefineInput, BuildDataOptions<TTransients>>;
+    traits?: {
+        [traitName: TraitName]: LoginLogFactoryTrait<TTransients>;
+    };
+} & CallbackDefineOptions<LoginLog, Prisma.LoginLogCreateInput, TTransients>;
+type LoginLogTraitKeys<TOptions extends LoginLogFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
+export interface LoginLogFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
+    readonly _factoryFor: "LoginLog";
+    build(inputData?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<Prisma.LoginLogCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<Prisma.LoginLogCreateInput>;
+    buildList(list: readonly Partial<Prisma.LoginLogCreateInput & TTransients>[]): PromiseLike<Prisma.LoginLogCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<Prisma.LoginLogCreateInput[]>;
+    pickForConnect(inputData: LoginLog): Pick<LoginLog, "id">;
+    create(inputData?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<LoginLog>;
+    createList(list: readonly Partial<Prisma.LoginLogCreateInput & TTransients>[]): PromiseLike<LoginLog[]>;
+    createList(count: number, item?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<LoginLog[]>;
+    createForConnect(inputData?: Partial<Prisma.LoginLogCreateInput & TTransients>): PromiseLike<Pick<LoginLog, "id">>;
+}
+export interface LoginLogFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends LoginLogFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): LoginLogFactoryInterfaceWithoutTraits<TTransients>;
+}
+interface LoginLogFactoryBuilder {
+    <TOptions extends LoginLogFactoryDefineOptions>(options?: TOptions): LoginLogFactoryInterface<{}, LoginLogTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends LoginLogTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends LoginLogFactoryDefineOptions<TTransients>>(options?: TOptions) => LoginLogFactoryInterface<TTransients, LoginLogTraitKeys<TOptions>>;
+}
+/**
+ * Define factory for {@link LoginLog} model.
+ *
+ * @param options
+ * @returns factory {@link LoginLogFactoryInterface}
+ */
+export declare const defineLoginLogFactory: LoginLogFactoryBuilder;
 type PostauthorFactory = {
     _factoryFor: "User";
     build: () => PromiseLike<Prisma.UserCreateNestedOneWithoutPostsInput["create"]>;
@@ -60,27 +118,35 @@ type PostFactoryDefineInput = {
     comments?: Prisma.CommentCreateNestedManyWithoutPostInput;
     categories?: Prisma.CategoryCreateNestedManyWithoutPostsInput;
 };
-type PostFactoryDefineOptions = {
-    defaultData: Resolver<PostFactoryDefineInput, BuildDataOptions>;
+type PostTransientFields = Record<string, unknown> & Partial<Record<keyof PostFactoryDefineInput, never>>;
+type PostFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
+type PostFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData: Resolver<PostFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: string | symbol]: PostFactoryTrait<TTransients>;
     };
-};
-type PostTraitKeys<TOptions extends PostFactoryDefineOptions> = keyof TOptions["traits"];
-export interface PostFactoryInterfaceWithoutTraits {
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
+type PostTraitKeys<TOptions extends PostFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
+export interface PostFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Post";
-    build(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    build(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput[]>;
     pickForConnect(inputData: Post): Pick<Post, "id">;
-    create(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Post>;
-    createList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Post[]>;
-    createForConnect(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Pick<Post, "id">>;
+    create(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post>;
+    createList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Post[]>;
+    createList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post[]>;
+    createForConnect(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Pick<Post, "id">>;
 }
-export interface PostFactoryInterface<TOptions extends PostFactoryDefineOptions = PostFactoryDefineOptions> extends PostFactoryInterfaceWithoutTraits {
-    use(name: PostTraitKeys<TOptions>, ...names: readonly PostTraitKeys<TOptions>[]): PostFactoryInterfaceWithoutTraits;
+export interface PostFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends PostFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): PostFactoryInterfaceWithoutTraits<TTransients>;
+}
+interface PostFactoryBuilder {
+    <TOptions extends PostFactoryDefineOptions>(options: TOptions): PostFactoryInterface<{}, PostTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends PostTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends PostFactoryDefineOptions<TTransients>>(options: TOptions) => PostFactoryInterface<TTransients, PostTraitKeys<TOptions>>;
 }
 /**
  * Define factory for {@link Post} model.
@@ -88,7 +154,7 @@ export interface PostFactoryInterface<TOptions extends PostFactoryDefineOptions
  * @param options
  * @returns factory {@link PostFactoryInterface}
  */
-export declare function definePostFactory<TOptions extends PostFactoryDefineOptions>(options: TOptions): PostFactoryInterface<TOptions>;
+export declare const definePostFactory: PostFactoryBuilder;
 type CommentpostFactory = {
     _factoryFor: "Post";
     build: () => PromiseLike<Prisma.PostCreateNestedOneWithoutCommentsInput["create"]>;
@@ -105,27 +171,35 @@ type CommentFactoryDefineInput = {
     post: CommentpostFactory | Prisma.PostCreateNestedOneWithoutCommentsInput;
     author: CommentauthorFactory | Prisma.UserCreateNestedOneWithoutCommentsInput;
 };
-type CommentFactoryDefineOptions = {
-    defaultData: Resolver<CommentFactoryDefineInput, BuildDataOptions>;
+type CommentTransientFields = Record<string, unknown> & Partial<Record<keyof CommentFactoryDefineInput, never>>;
+type CommentFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<CommentFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Comment, Prisma.CommentCreateInput, TTransients>;
+type CommentFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData: Resolver<CommentFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<CommentFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: string | symbol]: CommentFactoryTrait<TTransients>;
     };
-};
-type CommentTraitKeys<TOptions extends CommentFactoryDefineOptions> = keyof TOptions["traits"];
-export interface CommentFactoryInterfaceWithoutTraits {
+} & CallbackDefineOptions<Comment, Prisma.CommentCreateInput, TTransients>;
+type CommentTraitKeys<TOptions extends CommentFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
+export interface CommentFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Comment";
-    build(inputData?: Partial<Prisma.CommentCreateInput>): PromiseLike<Prisma.CommentCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.CommentCreateInput>): PromiseLike<Prisma.CommentCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.CommentCreateInput>[]): PromiseLike<Prisma.CommentCreateInput[]>;
+    build(inputData?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Prisma.CommentCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Prisma.CommentCreateInput>;
+    buildList(list: readonly Partial<Prisma.CommentCreateInput & TTransients>[]): PromiseLike<Prisma.CommentCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Prisma.CommentCreateInput[]>;
     pickForConnect(inputData: Comment): Pick<Comment, "id">;
-    create(inputData?: Partial<Prisma.CommentCreateInput>): PromiseLike<Comment>;
-    createList(inputData: number | readonly Partial<Prisma.CommentCreateInput>[]): PromiseLike<Comment[]>;
-    createForConnect(inputData?: Partial<Prisma.CommentCreateInput>): PromiseLike<Pick<Comment, "id">>;
+    create(inputData?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Comment>;
+    createList(list: readonly Partial<Prisma.CommentCreateInput & TTransients>[]): PromiseLike<Comment[]>;
+    createList(count: number, item?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Comment[]>;
+    createForConnect(inputData?: Partial<Prisma.CommentCreateInput & TTransients>): PromiseLike<Pick<Comment, "id">>;
+}
+export interface CommentFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends CommentFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): CommentFactoryInterfaceWithoutTraits<TTransients>;
 }
-export interface CommentFactoryInterface<TOptions extends CommentFactoryDefineOptions = CommentFactoryDefineOptions> extends CommentFactoryInterfaceWithoutTraits {
-    use(name: CommentTraitKeys<TOptions>, ...names: readonly CommentTraitKeys<TOptions>[]): CommentFactoryInterfaceWithoutTraits;
+interface CommentFactoryBuilder {
+    <TOptions extends CommentFactoryDefineOptions>(options: TOptions): CommentFactoryInterface<{}, CommentTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends CommentTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends CommentFactoryDefineOptions<TTransients>>(options: TOptions) => CommentFactoryInterface<TTransients, CommentTraitKeys<TOptions>>;
 }
 /**
  * Define factory for {@link Comment} model.
@@ -133,33 +207,41 @@ export interface CommentFactoryInterface<TOptions extends CommentFactoryDefineOp
  * @param options
  * @returns factory {@link CommentFactoryInterface}
  */
-export declare function defineCommentFactory<TOptions extends CommentFactoryDefineOptions>(options: TOptions): CommentFactoryInterface<TOptions>;
+export declare const defineCommentFactory: CommentFactoryBuilder;
 type CategoryFactoryDefineInput = {
     id?: string;
     name?: string;
     posts?: Prisma.PostCreateNestedManyWithoutCategoriesInput;
 };
-type CategoryFactoryDefineOptions = {
-    defaultData?: Resolver<CategoryFactoryDefineInput, BuildDataOptions>;
+type CategoryTransientFields = Record<string, unknown> & Partial<Record<keyof CategoryFactoryDefineInput, never>>;
+type CategoryFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Category, Prisma.CategoryCreateInput, TTransients>;
+type CategoryFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<CategoryFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: CategoryFactoryTrait<TTransients>;
     };
-};
-type CategoryTraitKeys<TOptions extends CategoryFactoryDefineOptions> = keyof TOptions["traits"];
-export interface CategoryFactoryInterfaceWithoutTraits {
+} & CallbackDefineOptions<Category, Prisma.CategoryCreateInput, TTransients>;
+type CategoryTraitKeys<TOptions extends CategoryFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
+export interface CategoryFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Category";
-    build(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Prisma.CategoryCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Prisma.CategoryCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]): PromiseLike<Prisma.CategoryCreateInput[]>;
+    build(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput>;
+    buildList(list: readonly Partial<Prisma.CategoryCreateInput & TTransients>[]): PromiseLike<Prisma.CategoryCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput[]>;
     pickForConnect(inputData: Category): Pick<Category, "id">;
-    create(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Category>;
-    createList(inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]): PromiseLike<Category[]>;
-    createForConnect(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Pick<Category, "id">>;
+    create(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Category>;
+    createList(list: readonly Partial<Prisma.CategoryCreateInput & TTransients>[]): PromiseLike<Category[]>;
+    createList(count: number, item?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Category[]>;
+    createForConnect(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Pick<Category, "id">>;
+}
+export interface CategoryFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends CategoryFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): CategoryFactoryInterfaceWithoutTraits<TTransients>;
 }
-export interface CategoryFactoryInterface<TOptions extends CategoryFactoryDefineOptions = CategoryFactoryDefineOptions> extends CategoryFactoryInterfaceWithoutTraits {
-    use(name: CategoryTraitKeys<TOptions>, ...names: readonly CategoryTraitKeys<TOptions>[]): CategoryFactoryInterfaceWithoutTraits;
+interface CategoryFactoryBuilder {
+    <TOptions extends CategoryFactoryDefineOptions>(options?: TOptions): CategoryFactoryInterface<{}, CategoryTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends CategoryTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends CategoryFactoryDefineOptions<TTransients>>(options?: TOptions) => CategoryFactoryInterface<TTransients, CategoryTraitKeys<TOptions>>;
 }
 /**
  * Define factory for {@link Category} model.
@@ -167,4 +249,4 @@ export interface CategoryFactoryInterface<TOptions extends CategoryFactoryDefine
  * @param options
  * @returns factory {@link CategoryFactoryInterface}
  */
-export declare function defineCategoryFactory<TOptions extends CategoryFactoryDefineOptions>(options?: TOptions): CategoryFactoryInterface<TOptions>;
+export declare const defineCategoryFactory: CategoryFactoryBuilder;
diff --git a/examples/example-prj/src/__generated__/fabbrica/index.js b/examples/example-prj/src/__generated__/fabbrica/index.js
index 37d5256..df2bbd3 100644
--- a/examples/example-prj/src/__generated__/fabbrica/index.js
+++ b/examples/example-prj/src/__generated__/fabbrica/index.js
@@ -1,10 +1,6 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.initialize = exports.resetScalarFieldValueGenerator = exports.registerScalarFieldValueGenerator = exports.resetSequence = void 0;
-exports.defineUserFactory = defineUserFactory;
-exports.definePostFactory = definePostFactory;
-exports.defineCommentFactory = defineCommentFactory;
-exports.defineCategoryFactory = defineCategoryFactory;
+exports.defineCategoryFactory = exports.defineCommentFactory = exports.definePostFactory = exports.defineLoginLogFactory = exports.defineUserFactory = exports.initialize = exports.resetScalarFieldValueGenerator = exports.registerScalarFieldValueGenerator = exports.resetSequence = void 0;
 const internal_1 = require("@quramy/prisma-fabbrica/lib/internal");
 var internal_2 = require("@quramy/prisma-fabbrica/lib/internal");
 Object.defineProperty(exports, "resetSequence", { enumerable: true, get: function () { return internal_2.resetSequence; } });
@@ -24,6 +20,9 @@ const modelFieldDefinitions = [{
                 type: "Comment",
                 relationName: "CommentToUser"
             }]
+    }, {
+        name: "LoginLog",
+        fields: []
     }, {
         name: "Post",
         fields: [{
@@ -65,37 +64,56 @@ function autoGenerateUserScalarsOrEnums({ seq }) {
         name: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "User", fieldName: "name", isId: false, isUnique: false, seq })
     };
 }
-function defineUserFactoryInternal({ defaultData: defaultDataResolver, traits: traitsDefs = {} }) {
+function defineUserFactoryInternal({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }, defaultTransientFieldValues) {
     const getFactoryWithTraits = (traitKeys = []) => {
         const seqKey = {};
         const getSeq = () => (0, internal_1.getSequenceCounter)(seqKey);
         const screen = (0, internal_1.createScreener)("User", modelFieldDefinitions);
+        const handleAfterBuild = (0, internal_1.createCallbackChain)([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = (0, internal_1.createCallbackChain)([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = (0, internal_1.createCallbackChain)([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
         const build = async (inputData = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
             const resolveValue = (0, internal_1.normalizeResolver)(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
                 const resolveTraitValue = (0, internal_1.normalizeResolver)(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => build(data)));
+        const buildList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => build(data)));
         const pickForConnect = (inputData) => ({
             id: inputData.id
         });
         const create = async (inputData = {}) => {
+            const [transientFields] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => create(data)));
+        const createList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => create(data)));
         const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User",
@@ -123,9 +141,97 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver, traits: t
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-function defineUserFactory(options) {
-    return defineUserFactoryInternal(options ?? {});
+exports.defineUserFactory = ((options) => {
+    return defineUserFactoryInternal(options ?? {}, {});
+});
+exports.defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
+function autoGenerateLoginLogScalarsOrEnums({ seq }) {
+    return {
+        userId: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "LoginLog", fieldName: "userId", isId: false, isUnique: false, seq }),
+        clientId: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "LoginLog", fieldName: "clientId", isId: false, isUnique: false, seq })
+    };
+}
+function defineLoginLogFactoryInternal({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }, defaultTransientFieldValues) {
+    const getFactoryWithTraits = (traitKeys = []) => {
+        const seqKey = {};
+        const getSeq = () => (0, internal_1.getSequenceCounter)(seqKey);
+        const screen = (0, internal_1.createScreener)("LoginLog", modelFieldDefinitions);
+        const handleAfterBuild = (0, internal_1.createCallbackChain)([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = (0, internal_1.createCallbackChain)([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = (0, internal_1.createCallbackChain)([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData = {}) => {
+            const seq = getSeq();
+            const requiredScalarData = autoGenerateLoginLogScalarsOrEnums({ seq });
+            const resolveValue = (0, internal_1.normalizeResolver)(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
+            const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
+                const acc = await queue;
+                const resolveTraitValue = (0, internal_1.normalizeResolver)(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
+                return {
+                    ...acc,
+                    ...traitData,
+                };
+            }, resolveValue(resolverInput));
+            const defaultAssociations = {};
+            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
+            return data;
+        };
+        const buildList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => build(data)));
+        const pickForConnect = (inputData) => ({
+            id: inputData.id
+        });
+        const create = async (inputData = {}) => {
+            const [transientFields] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const data = await build(inputData).then(screen);
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient().loginLog.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
+        };
+        const createList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => create(data)));
+        const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect);
+        return {
+            _factoryFor: "LoginLog",
+            build,
+            buildList,
+            buildCreateInput: build,
+            pickForConnect,
+            create,
+            createList,
+            createForConnect,
+        };
+    };
+    const factory = getFactoryWithTraits();
+    const useTraits = (name, ...names) => {
+        return getFactoryWithTraits([name, ...names]);
+    };
+    return {
+        ...factory,
+        use: useTraits,
+    };
 }
+/**
+ * Define factory for {@link LoginLog} model.
+ *
+ * @param options
+ * @returns factory {@link LoginLogFactoryInterface}
+ */
+exports.defineLoginLogFactory = ((options) => {
+    return defineLoginLogFactoryInternal(options ?? {}, {});
+});
+exports.defineLoginLogFactory.withTransientFields = defaultTransientFieldValues => options => defineLoginLogFactoryInternal(options ?? {}, defaultTransientFieldValues);
 function isPostauthorFactory(x) {
     return x?._factoryFor === "User";
 }
@@ -135,41 +241,60 @@ function autoGeneratePostScalarsOrEnums({ seq }) {
         title: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "Post", fieldName: "title", isId: false, isUnique: false, seq })
     };
 }
-function definePostFactoryInternal({ defaultData: defaultDataResolver, traits: traitsDefs = {} }) {
+function definePostFactoryInternal({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }, defaultTransientFieldValues) {
     const getFactoryWithTraits = (traitKeys = []) => {
         const seqKey = {};
         const getSeq = () => (0, internal_1.getSequenceCounter)(seqKey);
         const screen = (0, internal_1.createScreener)("Post", modelFieldDefinitions);
+        const handleAfterBuild = (0, internal_1.createCallbackChain)([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = (0, internal_1.createCallbackChain)([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = (0, internal_1.createCallbackChain)([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
         const build = async (inputData = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq });
             const resolveValue = (0, internal_1.normalizeResolver)(defaultDataResolver);
+            const [transientFields, filteredInputData] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
                 const resolveTraitValue = (0, internal_1.normalizeResolver)(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 author: isPostauthorFactory(defaultData.author) ? {
                     create: await defaultData.author.build()
                 } : defaultData.author
             };
-            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => build(data)));
+        const buildList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => build(data)));
         const pickForConnect = (inputData) => ({
             id: inputData.id
         });
         const create = async (inputData = {}) => {
+            const [transientFields] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient().post.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient().post.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => create(data)));
+        const createList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => create(data)));
         const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Post",
@@ -197,9 +322,10 @@ function definePostFactoryInternal({ defaultData: defaultDataResolver, traits: t
  * @param options
  * @returns factory {@link PostFactoryInterface}
  */
-function definePostFactory(options) {
-    return definePostFactoryInternal(options);
-}
+exports.definePostFactory = ((options) => {
+    return definePostFactoryInternal(options, {});
+});
+exports.definePostFactory.withTransientFields = defaultTransientFieldValues => options => definePostFactoryInternal(options, defaultTransientFieldValues);
 function isCommentpostFactory(x) {
     return x?._factoryFor === "Post";
 }
@@ -212,24 +338,38 @@ function autoGenerateCommentScalarsOrEnums({ seq }) {
         body: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "Comment", fieldName: "body", isId: false, isUnique: false, seq })
     };
 }
-function defineCommentFactoryInternal({ defaultData: defaultDataResolver, traits: traitsDefs = {} }) {
+function defineCommentFactoryInternal({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }, defaultTransientFieldValues) {
     const getFactoryWithTraits = (traitKeys = []) => {
         const seqKey = {};
         const getSeq = () => (0, internal_1.getSequenceCounter)(seqKey);
         const screen = (0, internal_1.createScreener)("Comment", modelFieldDefinitions);
+        const handleAfterBuild = (0, internal_1.createCallbackChain)([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = (0, internal_1.createCallbackChain)([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = (0, internal_1.createCallbackChain)([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
         const build = async (inputData = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateCommentScalarsOrEnums({ seq });
             const resolveValue = (0, internal_1.normalizeResolver)(defaultDataResolver);
+            const [transientFields, filteredInputData] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
                 const resolveTraitValue = (0, internal_1.normalizeResolver)(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 post: isCommentpostFactory(defaultData.post) ? {
                     create: await defaultData.post.build()
@@ -238,18 +378,23 @@ function defineCommentFactoryInternal({ defaultData: defaultDataResolver, traits
                     create: await defaultData.author.build()
                 } : defaultData.author
             };
-            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => build(data)));
+        const buildList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => build(data)));
         const pickForConnect = (inputData) => ({
             id: inputData.id
         });
         const create = async (inputData = {}) => {
+            const [transientFields] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient().comment.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient().comment.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => create(data)));
+        const createList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => create(data)));
         const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Comment",
@@ -277,46 +422,66 @@ function defineCommentFactoryInternal({ defaultData: defaultDataResolver, traits
  * @param options
  * @returns factory {@link CommentFactoryInterface}
  */
-function defineCommentFactory(options) {
-    return defineCommentFactoryInternal(options);
-}
+exports.defineCommentFactory = ((options) => {
+    return defineCommentFactoryInternal(options, {});
+});
+exports.defineCommentFactory.withTransientFields = defaultTransientFieldValues => options => defineCommentFactoryInternal(options, defaultTransientFieldValues);
 function autoGenerateCategoryScalarsOrEnums({ seq }) {
     return {
         id: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "Category", fieldName: "id", isId: true, isUnique: false, seq }),
         name: (0, internal_1.getScalarFieldValueGenerator)().String({ modelName: "Category", fieldName: "name", isId: false, isUnique: true, seq })
     };
 }
-function defineCategoryFactoryInternal({ defaultData: defaultDataResolver, traits: traitsDefs = {} }) {
+function defineCategoryFactoryInternal({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }, defaultTransientFieldValues) {
     const getFactoryWithTraits = (traitKeys = []) => {
         const seqKey = {};
         const getSeq = () => (0, internal_1.getSequenceCounter)(seqKey);
         const screen = (0, internal_1.createScreener)("Category", modelFieldDefinitions);
+        const handleAfterBuild = (0, internal_1.createCallbackChain)([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = (0, internal_1.createCallbackChain)([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = (0, internal_1.createCallbackChain)([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
         const build = async (inputData = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateCategoryScalarsOrEnums({ seq });
             const resolveValue = (0, internal_1.normalizeResolver)(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
                 const resolveTraitValue = (0, internal_1.normalizeResolver)(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => build(data)));
+        const buildList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => build(data)));
         const pickForConnect = (inputData) => ({
             id: inputData.id
         });
         const create = async (inputData = {}) => {
+            const [transientFields] = (0, internal_1.destructure)(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient().category.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient().category.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData) => Promise.all((0, internal_1.normalizeList)(inputData).map(data => create(data)));
+        const createList = (...args) => Promise.all((0, internal_1.normalizeList)(...args).map(data => create(data)));
         const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Category",
@@ -344,6 +509,7 @@ function defineCategoryFactoryInternal({ defaultData: defaultDataResolver, trait
  * @param options
  * @returns factory {@link CategoryFactoryInterface}
  */
-function defineCategoryFactory(options) {
-    return defineCategoryFactoryInternal(options ?? {});
-}
+exports.defineCategoryFactory = ((options) => {
+    return defineCategoryFactoryInternal(options ?? {}, {});
+});
+exports.defineCategoryFactory.withTransientFields = defaultTransientFieldValues => options => defineCategoryFactoryInternal(options ?? {}, defaultTransientFieldValues);
diff --git a/package-lock.json b/package-lock.json
index 32968dd..c9b1f3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,7 +26,7 @@
       }
     },
     "examples/example-prj": {
-      "version": "2.1.5",
+      "version": "2.2.0-alpha.4",
       "dependencies": {
         "@prisma/client": "*",
         "@types/uuid": "8.3.4",
@@ -5555,7 +5555,7 @@
       }
     },
     "packages/artifact-testing": {
-      "version": "2.1.5",
+      "version": "2.2.0-alpha.4",
       "devDependencies": {
         "@prisma/internals": "5.15.1",
         "@types/jest": "29.5.12",
@@ -5566,7 +5566,7 @@
     },
     "packages/prisma-fabbrica": {
       "name": "@quramy/prisma-fabbrica",
-      "version": "2.1.5",
+      "version": "2.2.0-alpha.4",
       "license": "MIT",
       "dependencies": {
         "@prisma/generator-helper": "^5.0.0",
diff --git a/packages/prisma-fabbrica/package.json b/packages/prisma-fabbrica/package.json
index da1095b..b2ffe48 100644
--- a/packages/prisma-fabbrica/package.json
+++ b/packages/prisma-fabbrica/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@quramy/prisma-fabbrica",
-  "version": "2.1.5",
+  "version": "2.2.0-alpha.4",
   "description": " Prisma generator for model factories",
   "main": "./lib/index.js",
   "types": "./lib/index.d.ts",
diff --git a/packages/prisma-fabbrica/src/helpers/callback.ts b/packages/prisma-fabbrica/src/helpers/callback.ts
new file mode 100644
index 0000000..e4797f6
--- /dev/null
+++ b/packages/prisma-fabbrica/src/helpers/callback.ts
@@ -0,0 +1,11 @@
+export type CallbackFn<T extends any[]> = (...args: T) => unknown;
+
+export function createCallbackChain<T extends any[]>(callbackFns: readonly (CallbackFn<T> | undefined)[]) {
+  return async (...args: T) => {
+    await callbackFns.reduce(async (acc, fn) => {
+      await acc;
+      if (!fn) return;
+      await fn(...args);
+    }, Promise.resolve());
+  };
+}
diff --git a/packages/prisma-fabbrica/src/helpers/index.ts b/packages/prisma-fabbrica/src/helpers/index.ts
index 21004d2..678dde9 100644
--- a/packages/prisma-fabbrica/src/helpers/index.ts
+++ b/packages/prisma-fabbrica/src/helpers/index.ts
@@ -3,3 +3,5 @@ export * from "./stringConverter";
 export * from "./sequence";
 export * from "./selectors";
 export * from "./list";
+export * from "./callback";
+export * from "./transientFields";
diff --git a/packages/prisma-fabbrica/src/helpers/list.ts b/packages/prisma-fabbrica/src/helpers/list.ts
index 977a811..67dedd5 100644
--- a/packages/prisma-fabbrica/src/helpers/list.ts
+++ b/packages/prisma-fabbrica/src/helpers/list.ts
@@ -1,7 +1,10 @@
-export function normalizeList<T extends Record<string, unknown>>(input: number | readonly T[]) {
-  if (typeof input === "number") {
-    return [...new Array(input).keys()].map(() => ({}) as T);
+export function normalizeList<T extends Record<string, unknown>>(...args: any[]): T[] {
+  const [countOrList, item = {}] = args;
+  if (typeof countOrList === "number") {
+    return [...new Array(countOrList).keys()].map(() => item) as T[];
+  } else if (Array.isArray(countOrList)) {
+    return countOrList as T[];
   } else {
-    return input;
+    throw new Error("Illegal Argument");
   }
 }
diff --git a/packages/prisma-fabbrica/src/helpers/transientFields.ts b/packages/prisma-fabbrica/src/helpers/transientFields.ts
new file mode 100644
index 0000000..6e484d7
--- /dev/null
+++ b/packages/prisma-fabbrica/src/helpers/transientFields.ts
@@ -0,0 +1,14 @@
+export function destructure<T extends Record<string, unknown>, S extends Record<string, unknown>>(
+  defaultValues: T,
+  inputData: S | null | undefined,
+) {
+  const merged = { ...defaultValues } as any;
+  const filteredInputData = (inputData ?? {}) as S;
+  for (const key of Object.keys(defaultValues)) {
+    if (filteredInputData[key] != null) {
+      merged[key] = filteredInputData[key];
+      delete filteredInputData[key];
+    }
+  }
+  return [merged, filteredInputData] as [T, S];
+}
diff --git a/packages/prisma-fabbrica/src/internal.ts b/packages/prisma-fabbrica/src/internal.ts
index 7ab16ef..9e473c9 100644
--- a/packages/prisma-fabbrica/src/internal.ts
+++ b/packages/prisma-fabbrica/src/internal.ts
@@ -1,6 +1,13 @@
 export { getClient } from "./clientHolder";
 export { ModelWithFields, createScreener } from "./relations/screen";
-export { Resolver, normalizeResolver, normalizeList, getSequenceCounter } from "./helpers";
+export {
+  Resolver,
+  normalizeResolver,
+  normalizeList,
+  getSequenceCounter,
+  createCallbackChain,
+  destructure,
+} from "./helpers";
 export { createInitializer, initialize, resetSequence } from "./initialize";
 export type { InitializeOptions } from "./initialize";
 export {
diff --git a/packages/prisma-fabbrica/src/templates/index.ts b/packages/prisma-fabbrica/src/templates/index.ts
index 82d8de7..fe775ac 100644
--- a/packages/prisma-fabbrica/src/templates/index.ts
+++ b/packages/prisma-fabbrica/src/templates/index.ts
@@ -86,6 +86,8 @@ export const header = (prismaClientModuleSpecifier: string) =>
       normalizeResolver,
       normalizeList,
       getSequenceCounter,
+      createCallbackChain,
+      destructure
     } from "@quramy/prisma-fabbrica/lib/internal";
     import type {
       ModelWithFields,
@@ -94,20 +96,25 @@ export const header = (prismaClientModuleSpecifier: string) =>
     export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
   `();
 
-export const buildDataOptions = () =>
-  template.statement<ts.TypeAliasDeclaration>`
-    type BuildDataOptions = {
-      readonly seq: number;
-    };
-  `();
-
 export const importStatement = (specifier: string, prismaClientModuleSpecifier: string) =>
   template.statement<ts.ImportDeclaration>`
     import type { ${() => ast.identifier(specifier)} } from ${() => ast.stringLiteral(prismaClientModuleSpecifier)};
   `();
 
-export const initializer = () =>
+export const genericDeclarations = () =>
   template.sourceFile`
+    type BuildDataOptions<TTransients extends Record<string, unknown>> = {
+      readonly seq: number;
+    } & TTransients;
+
+    type TraitName = string | symbol;
+
+    type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+      onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+      onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+      onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
+    };
+
     const initializer = createInitializer();
     const { getClient } = initializer;
     export const { initialize } = initializer;
@@ -227,37 +234,56 @@ export const modelFactoryDefineInput = (model: DMMF.Model, inputType: DMMF.Input
     MODEL_FACTORY_DEFINE_INPUT: ast.identifier(`${model.name}FactoryDefineInput`),
   });
 
-export const modelFactoryDefineOptions = (modelName: string, isOpionalDefaultData: boolean) => {
+export const modelTransientFields = (model: DMMF.Model) =>
+  template.statement<ts.TypeAliasDeclaration>`
+    type MODEL_TRANSIENT_FIELDS = Record<string, unknown> & Partial<Record<keyof MODEL_FACTORY_DEFINE_INPUT, never>>;
+  `({
+    MODEL_TRANSIENT_FIELDS: ast.identifier(`${model.name}TransientFields`),
+    MODEL_FACTORY_DEFINE_INPUT: ast.identifier(`${model.name}FactoryDefineInput`),
+  });
+
+export const modelFactoryTrait = (model: DMMF.Model) =>
+  template.statement<ts.TypeAliasDeclaration>`
+    type MODEL_FACTORY_TRAIT<TTransients extends Record<string, unknown>> = {
+      data?: Resolver<Partial<MODEL_FACTORY_DEFINE_INPUT>, BuildDataOptions<TTransients>>;
+    } & CallbackDefineOptions<MODEL_TYPE, Prisma.MODEL_CREATE_INPUT, TTransients>;
+  `({
+    MODEL_TYPE: ast.identifier(model.name),
+    MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
+    MODEL_FACTORY_DEFINE_INPUT: ast.identifier(`${model.name}FactoryDefineInput`),
+    MODEL_FACTORY_TRAIT: ast.identifier(`${model.name}FactoryTrait`),
+  });
+
+export const modelFactoryDefineOptions = (model: DMMF.Model, isOpionalDefaultData: boolean) => {
   const compiled = isOpionalDefaultData
     ? template.statement<ts.TypeAliasDeclaration>`
-        type MODEL_FACTORY_DEFINE_OPTIONS = {
-          defaultData?: Resolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions>;
+        type MODEL_FACTORY_DEFINE_OPTIONS<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+          defaultData?: Resolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions<TTransients>>;
           traits?: {
-            [traitName: string | symbol]: { 
-              data: Resolver<Partial<MODEL_FACTORY_DEFINE_INPUT>, BuildDataOptions>;
-            }
+            [traitName: TraitName]: MODEL_FACTORY_TRAIT<TTransients>;
           };
-        };
+        } & CallbackDefineOptions<MODEL_TYPE, Prisma.MODEL_CREATE_INPUT, TTransients>;
       `
     : template.statement<ts.TypeAliasDeclaration>`
-        type MODEL_FACTORY_DEFINE_OPTIONS = {
-          defaultData: Resolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions>;
+        type MODEL_FACTORY_DEFINE_OPTIONS<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+          defaultData: Resolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions<TTransients>>;
           traits?: {
-            [traitName: string | symbol]: { 
-              data: Resolver<Partial<MODEL_FACTORY_DEFINE_INPUT>, BuildDataOptions>;
-            }
+            [traitName: string | symbol]: MODEL_FACTORY_TRAIT<TTransients>;
           };
-        };
+        } & CallbackDefineOptions<MODEL_TYPE, Prisma.MODEL_CREATE_INPUT, TTransients>;
       `;
   return compiled({
-    MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${modelName}FactoryDefineOptions`),
-    MODEL_FACTORY_DEFINE_INPUT: ast.identifier(`${modelName}FactoryDefineInput`),
+    MODEL_TYPE: ast.identifier(model.name),
+    MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
+    MODEL_FACTORY_DEFINE_INPUT: ast.identifier(`${model.name}FactoryDefineInput`),
+    MODEL_FACTORY_TRAIT: ast.identifier(`${model.name}FactoryTrait`),
+    MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
   });
 };
 
 export const modelTraitKeys = (model: DMMF.Model) =>
   template.statement`
-    type MODEL_TRAIT_KEYS<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS> = keyof TOptions["traits"];
+    type MODEL_TRAIT_KEYS<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS<any>> = Exclude<keyof TOptions["traits"], number>;
   `({
     MODEL_TRAIT_KEYS: ast.identifier(`${model.name}TraitKeys`),
     MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
@@ -265,20 +291,25 @@ export const modelTraitKeys = (model: DMMF.Model) =>
 
 export const modelFactoryInterfaceWithoutTraits = (model: DMMF.Model) =>
   template.statement`
-    export interface MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS {
+    export interface MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS<TTransients extends Record<string, unknown> {
       readonly _factoryFor: ${() => ast.literalTypeNode(ast.stringLiteral(model.name))}
-      build(inputData?: Partial<Prisma.MODEL_CREATE_INPUT>): PromiseLike<Prisma.MODEL_CREATE_INPUT>
-      buildCreateInput(inputData?: Partial<Prisma.MODEL_CREATE_INPUT>): PromiseLike<Prisma.MODEL_CREATE_INPUT>
-      buildList(inputData: number | readonly Partial<Prisma.MODEL_CREATE_INPUT>[]): PromiseLike<Prisma.MODEL_CREATE_INPUT[]>
+      build(inputData?: CREATE_INPUT_TYPE): PromiseLike<Prisma.MODEL_CREATE_INPUT>
+      buildCreateInput(inputData?: CREATE_INPUT_TYPE): PromiseLike<Prisma.MODEL_CREATE_INPUT>
+      buildList(list: readonly CREATE_INPUT_TYPE[]): PromiseLike<Prisma.MODEL_CREATE_INPUT[]>
+      buildList(count: number, item?: CREATE_INPUT_TYPE): PromiseLike<Prisma.MODEL_CREATE_INPUT[]>
       pickForConnect(inputData: MODEL_TYPE): Pick<MODEL_TYPE, MODEL_ID_COLS>
-      create(inputData?: Partial<Prisma.MODEL_CREATE_INPUT>): PromiseLike<MODEL_TYPE>
-      createList(inputData: number | readonly Partial<Prisma.MODEL_CREATE_INPUT>[]): PromiseLike<MODEL_TYPE[]>
-      createForConnect(inputData?: Partial<Prisma.MODEL_CREATE_INPUT>): PromiseLike<Pick<MODEL_TYPE, MODEL_ID_COLS>>
+      create(inputData?: CREATE_INPUT_TYPE): PromiseLike<MODEL_TYPE>
+      createList(list: readonly CREATE_INPUT_TYPE[]): PromiseLike<MODEL_TYPE[]>
+      createList(count: number, item?: CREATE_INPUT_TYPE): PromiseLike<MODEL_TYPE[]>
+      createForConnect(inputData?: CREATE_INPUT_TYPE): PromiseLike<Pick<MODEL_TYPE, MODEL_ID_COLS>>
     }
   `({
     MODEL_TYPE: ast.identifier(model.name),
     MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS: ast.identifier(`${model.name}FactoryInterfaceWithoutTraits`),
     MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
+    CREATE_INPUT_TYPE: template.typeNode`Partial<Prisma.MODEL_CREATE_INPUT & TTransients>`({
+      MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
+    }),
     MODEL_ID_COLS: ast.unionTypeNode(
       getIdFieldNames(model).map(fieldName => ast.literalTypeNode(ast.stringLiteral(fieldName))),
     ),
@@ -286,14 +317,15 @@ export const modelFactoryInterfaceWithoutTraits = (model: DMMF.Model) =>
 
 export const modelFactoryInterface = (model: DMMF.Model) =>
   template.statement`
-    export interface MODEL_FACTORY_INTERFACE<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS = MODEL_FACTORY_DEFINE_OPTIONS>  extends MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS {
-      use(name: MODEL_TRAIT_KEYS<TOptions>, ...names: readonly MODEL_TRAIT_KEYS<TOptions>[]): MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS;
+    export interface MODEL_FACTORY_INTERFACE<
+      TTransients extends Record<string, unknown> = Record<string, unknown>,
+      TTraitName extends TraitName = TraitName
+    > extends MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS<TTransients> {
+      use(name: TTraitName, ...names: readonly TTraitName[]): MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS<TTransients>;
     }
   `({
     MODEL_FACTORY_INTERFACE: ast.identifier(`${model.name}FactoryInterface`),
     MODEL_FACTORY_INTERFACE_WITHOUT_TRAITS: ast.identifier(`${model.name}FactoryInterfaceWithoutTraits`),
-    MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
-    MODEL_TRAIT_KEYS: ast.identifier(`${model.name}TraitKeys`),
   });
 
 export const isModelAssociationFactory = (fieldType: DMMF.SchemaArg, model: DMMF.Model) => {
@@ -356,30 +388,51 @@ export const autoGenerateModelScalarsOrEnums = (
 
 export const defineModelFactoryInternal = (model: DMMF.Model, inputType: DMMF.InputType) =>
   template.statement<ts.FunctionDeclaration>`
-    function DEFINE_MODEL_FACTORY_INTERNAL<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>({
+    function DEFINE_MODEL_FACTORY_INTERNAL<TTransients extends Record<string, unknown>, TOptions extends MODEL_FACTORY_DEFINE_OPTIONS<TTransients>>({
       defaultData: defaultDataResolver,
+      onAfterBuild,
+      onBeforeCreate,
+      onAfterCreate,
       traits: traitsDefs = {}
-    }: TOptions): MODEL_FACTORY_INTERFACE<TOptions> {
+    }: TOptions, defaultTransientFieldValues: TTransients): MODEL_FACTORY_INTERFACE<TTransients, MODEL_TRAIT_KEYS<TOptions>> {
       const getFactoryWithTraits = (traitKeys: readonly MODEL_TRAIT_KEYS<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener(${() => ast.stringLiteral(model.name)}, modelFieldDefinitions);
 
+        const handleAfterBuild = createCallbackChain([
+          onAfterBuild,
+          ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+          ...traitKeys
+            .slice()
+            .reverse()
+            .map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+          onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+          onAfterCreate,
+          ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+
         const build = async (
-          inputData: Partial<Prisma.MODEL_CREATE_INPUT> = {}
+          inputData: CREATE_INPUT_TYPE = {}
         ) => {
           const seq = getSeq();
           const requiredScalarData = AUTO_GENERATE_MODEL_SCALARS_OR_ENUMS({ seq });
-          const resolveValue = normalizeResolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions>(DEFALUT_DATA_RESOLVER);
+          const resolveValue = normalizeResolver<MODEL_FACTORY_DEFINE_INPUT, BuildDataOptions<any>>(DEFALUT_DATA_RESOLVER);
+          const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+          const resolverInput = { seq, ...transientFields };
           const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
             const acc = await queue;
-            const resolveTraitValue = normalizeResolver<Partial<MODEL_FACTORY_DEFINE_INPUT>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-            const traitData = await resolveTraitValue({ seq });
+            const resolveTraitValue = normalizeResolver<Partial<MODEL_FACTORY_DEFINE_INPUT>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+            const traitData = await resolveTraitValue(resolverInput);
             return {
               ...acc,
               ...traitData,
             };
-          }, resolveValue({ seq });
+          }, resolveValue(resolverInput);
           const defaultAssociations = ${() =>
             ast.objectLiteralExpression(
               filterBelongsToField(model, inputType).map(field =>
@@ -397,13 +450,12 @@ export const defineModelFactoryInternal = (model: DMMF.Model, inputType: DMMF.In
               ),
               true,
             )};
-          const data: Prisma.MODEL_CREATE_INPUT = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData};
+          const data: Prisma.MODEL_CREATE_INPUT = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+          await handleAfterBuild(data, transientFields);
           return data;
         };
 
-        const buildList = (
-          inputData: number | readonly Partial<Prisma.MODEL_CREATE_INPUT>[]
-        ) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<CREATE_INPUT_TYPE>(...args).map(data => build(data)));
 
         const pickForConnect = (inputData: ${() => ast.typeReferenceNode(model.name)}) => (
           ${() =>
@@ -416,17 +468,19 @@ export const defineModelFactoryInternal = (model: DMMF.Model, inputType: DMMF.In
         );
 
         const create = async (
-          inputData: Partial<Prisma.MODEL_CREATE_INPUT> = {}
+          inputData: CREATE_INPUT_TYPE = {}
         ) => {
+          const [transientFields] = destructure(defaultTransientFieldValues, inputData);
           const data = await build(inputData).then(screen);
-          return await getClient<PrismaClient>().MODEL_KEY.create({ data });
+          await handleBeforeCreate(data, transientFields);
+          const createdData = await getClient<PrismaClient>().MODEL_KEY.create({ data });
+          await handleAfterCreate(createdData, transientFields);
+          return createdData;
         };
 
-        const createList = (
-          inputData: number | readonly Partial<Prisma.MODEL_CREATE_INPUT>[]
-        ) => Promise.all(normalizeList(inputData).map(data => create(data)));
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<CREATE_INPUT_TYPE>(...args).map(data => create(data)));
 
-        const createForConnect = (inputData: Partial<Prisma.MODEL_CREATE_INPUT> = {}) => create(inputData).then(pickForConnect);
+        const createForConnect = (inputData: CREATE_INPUT_TYPE = {}) => create(inputData).then(pickForConnect);
 
         return {
           _factoryFor: ${() => ast.stringLiteral(model.name)} as const,
@@ -457,22 +511,46 @@ export const defineModelFactoryInternal = (model: DMMF.Model, inputType: DMMF.In
     MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
     MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
     AUTO_GENERATE_MODEL_SCALARS_OR_ENUMS: ast.identifier(`autoGenerate${model.name}ScalarsOrEnums`),
+    CREATE_INPUT_TYPE: template.typeNode`Partial<Prisma.MODEL_CREATE_INPUT & TTransients>`({
+      MODEL_CREATE_INPUT: ast.identifier(`${model.name}CreateInput`),
+    }),
     DEFALUT_DATA_RESOLVER: filterRequiredInputObjectTypeField(inputType).length
       ? template.expression(`defaultDataResolver`)({})
       : template.expression(`defaultDataResolver ?? {}`)({}),
   });
 
+export const modelFactoryBuilder = (model: DMMF.Model, inputType: DMMF.InputType) => {
+  const compiled = filterRequiredInputObjectTypeField(inputType).length
+    ? template.statement<ts.InterfaceDeclaration>`
+        interface MODEL_FACTORY_BUILDER {
+          <TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options: TOptions): MODEL_FACTORY_INTERFACE<{}, MODEL_TRAIT_KEYS<TOptions>>;
+          withTransientFields: <TTransients extends MODEL_TRANSIENT_FIELDS>(defaultTransientFieldValues: TTransients) => <TOptions extends MODEL_FACTORY_DEFINE_OPTIONS<TTransients>>(options: TOptions) => MODEL_FACTORY_INTERFACE<TTransients, MODEL_TRAIT_KEYS<TOptions>>
+        }`
+    : template.statement<ts.InterfaceDeclaration>`
+        interface MODEL_FACTORY_BUILDER {
+          <TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options?: TOptions): MODEL_FACTORY_INTERFACE<{}, MODEL_TRAIT_KEYS<TOptions>>;
+          withTransientFields: <TTransients extends MODEL_TRANSIENT_FIELDS>(defaultTransientFieldValues: TTransients) => <TOptions extends MODEL_FACTORY_DEFINE_OPTIONS<TTransients>>(options?: TOptions) => MODEL_FACTORY_INTERFACE<TTransients, MODEL_TRAIT_KEYS<TOptions>>
+        }`;
+  return compiled({
+    MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
+    MODEL_FACTORY_INTERFACE: ast.identifier(`${model.name}FactoryInterface`),
+    MODEL_FACTORY_BUILDER: ast.identifier(`${model.name}FactoryBuilder`),
+    MODEL_TRAIT_KEYS: ast.identifier(`${model.name}TraitKeys`),
+    MODEL_TRANSIENT_FIELDS: ast.identifier(`${model.name}TransientFields`),
+  });
+};
+
 export const defineModelFactory = (model: DMMF.Model, inputType: DMMF.InputType) => {
   const compiled = filterRequiredInputObjectTypeField(inputType).length
-    ? template.statement<ts.FunctionDeclaration>`
-        export function DEFINE_MODEL_FACTORY<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options: TOptions): MODEL_FACTORY_INTERFACE<TOptions> {
-          return DEFINE_MODEL_FACTORY_INTERNAL(options);
-        }
+    ? template.statement<ts.Statement>`
+        export const DEFINE_MODEL_FACTORY = (<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options: TOptions): MODEL_FACTORY_INTERFACE<TOptions> => {
+          return DEFINE_MODEL_FACTORY_INTERNAL(options, {});
+        }) as MODEL_FACTORY_BUILDER;
       `
-    : template.statement<ts.FunctionDeclaration>`
-        export function DEFINE_MODEL_FACTORY<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options?: TOptions): MODEL_FACTORY_INTERFACE<TOptions> {
-          return DEFINE_MODEL_FACTORY_INTERNAL(options ?? {});
-        }
+    : template.statement<ts.Statement>`
+        export const DEFINE_MODEL_FACTORY = (<TOptions extends MODEL_FACTORY_DEFINE_OPTIONS>(options?: TOptions): MODEL_FACTORY_INTERFACE<TOptions> => {
+          return DEFINE_MODEL_FACTORY_INTERNAL(options ?? {}, {});
+        }) as MODEL_FACTORY_BUILDER;
       `;
 
   const tsDoc = `
@@ -488,10 +566,25 @@ Define factory for {@link ${model.name}} model.
       DEFINE_MODEL_FACTORY_INTERNAL: ast.identifier(`define${model.name}FactoryInternal`),
       MODEL_FACTORY_DEFINE_OPTIONS: ast.identifier(`${model.name}FactoryDefineOptions`),
       MODEL_FACTORY_INTERFACE: ast.identifier(`${model.name}FactoryInterface`),
+      MODEL_FACTORY_BUILDER: ast.identifier(`${model.name}FactoryBuilder`),
     }),
   );
 };
 
+export const assignWithTransientFields = (model: DMMF.Model, inputType: DMMF.InputType) => {
+  const compiled = filterRequiredInputObjectTypeField(inputType).length
+    ? template.statement<ts.ExpressionStatement>`
+        DEFINE_MODEL_FACTORY.withTransientFields = defaultTransientFieldValues => options => DEFINE_MODEL_FACTORY_INTERNAL(options, defaultTransientFieldValues);
+      `
+    : template.statement<ts.ExpressionStatement>`
+        DEFINE_MODEL_FACTORY.withTransientFields = defaultTransientFieldValues => options => DEFINE_MODEL_FACTORY_INTERNAL(options ?? {}, defaultTransientFieldValues);
+      `;
+  return compiled({
+    DEFINE_MODEL_FACTORY_INTERNAL: ast.identifier(`define${model.name}FactoryInternal`),
+    DEFINE_MODEL_FACTORY: ast.identifier(`define${model.name}Factory`),
+  });
+};
+
 export function getSourceFile({
   document,
   prismaClientModuleSpecifier = "@prisma/client",
@@ -518,8 +611,7 @@ export function getSourceFile({
     ...modelNames.map(modelName => importStatement(modelName, prismaClientModuleSpecifier)),
     ...modelEnums.map(enumName => importStatement(enumName, prismaClientModuleSpecifier)),
     ...header(prismaClientModuleSpecifier).statements,
-    insertLeadingBreakMarker(buildDataOptions()),
-    ...insertLeadingBreakMarker(initializer().statements),
+    ...insertLeadingBreakMarker(genericDeclarations().statements),
     insertLeadingBreakMarker(modelFieldDefinitions(document.datamodel.models)),
     ...document.datamodel.models
       .reduce(
@@ -536,14 +628,18 @@ export function getSourceFile({
           modelBelongsToRelationFactory(fieldType, model),
         ),
         modelFactoryDefineInput(model, createInputType),
-        modelFactoryDefineOptions(model.name, filterRequiredInputObjectTypeField(createInputType).length === 0),
+        modelTransientFields(model),
+        modelFactoryTrait(model),
+        modelFactoryDefineOptions(model, filterRequiredInputObjectTypeField(createInputType).length === 0),
         ...filterBelongsToField(model, createInputType).map(fieldType => isModelAssociationFactory(fieldType, model)),
         modelTraitKeys(model),
         modelFactoryInterfaceWithoutTraits(model),
         modelFactoryInterface(model),
         autoGenerateModelScalarsOrEnums(model, createInputType, document.schema.enumTypes.model ?? []),
         defineModelFactoryInternal(model, createInputType),
+        modelFactoryBuilder(model, createInputType),
         defineModelFactory(model, createInputType),
+        assignWithTransientFields(model, createInputType),
       ])
       .map(insertLeadingBreakMarker),
   ];


Test patch:
diff --git a/examples/example-prj/src/factoryInterface.test.ts b/examples/example-prj/src/factoryInterface.test.ts
new file mode 100644
index 0000000..fe95cbf
--- /dev/null
+++ b/examples/example-prj/src/factoryInterface.test.ts
@@ -0,0 +1,46 @@
+import { defineUserFactory, type UserFactoryInterface } from "./__generated__/fabbrica";
+import { defineLoginLogFactory, type LoginLogFactoryInterface } from "./__generated__/fabbrica";
+
+const prisma = jestPrisma.client;
+
+type LoginLogFactory = LoginLogFactoryInterface;
+
+function getLoginLogFactory(): LoginLogFactory {
+  return defineLoginLogFactory();
+}
+
+type UserTransientFields = {
+  loginCount: number;
+};
+
+type UserTraits = "withLoginRecords";
+
+type UserFactory = UserFactoryInterface<UserTransientFields, UserTraits>;
+
+function getUserFactory(): UserFactory {
+  return defineUserFactory.withTransientFields({
+    loginCount: 0,
+  } satisfies UserTransientFields)({
+    traits: {
+      withLoginRecords: {
+        onAfterCreate: async (user, { loginCount }) => {
+          await getLoginLogFactory().createList(loginCount, { userId: user.id });
+        },
+      },
+    },
+  });
+}
+
+describe("factory defined with interface", () => {
+  test("works correctly", async () => {
+    await getUserFactory().use("withLoginRecords").create({ id: "user01", loginCount: 3 });
+
+    await expect(
+      prisma.loginLog.count({
+        where: {
+          userId: "user01",
+        },
+      }),
+    ).resolves.toBe(3);
+  });
+});
diff --git a/examples/example-prj/src/trait.test.ts b/examples/example-prj/src/trait.test.ts
index b0f8ff3..74335e0 100644
--- a/examples/example-prj/src/trait.test.ts
+++ b/examples/example-prj/src/trait.test.ts
@@ -2,12 +2,28 @@ import {
   defineUserFactory,
   definePostFactory,
   defineCommentFactory,
-  CommentFactoryInterface,
+  type PostFactoryInterface,
+  type CommentFactoryInterface,
 } from "./__generated__/fabbrica";
 
 const prisma = jestPrisma.client;
 
-export const UserFactory = defineUserFactory();
+export const UserFactory = defineUserFactory({
+  traits: {
+    withSelfCommentedPost: {
+      onAfterCreate: async user => {
+        await getPostFactory().create({
+          author: {
+            connect: user,
+          },
+          comments: {
+            create: [await getCommentFactory().build({ author: { connect: user } })],
+          },
+        });
+      },
+    },
+  },
+});
 
 export const PostFactory = definePostFactory({
   defaultData: {
@@ -43,6 +59,10 @@ export const CommentFactory = defineCommentFactory({
   },
 });
 
+function getPostFactory(): PostFactoryInterface {
+  return PostFactory;
+}
+
 function getCommentFactory(): CommentFactoryInterface {
   return CommentFactory;
 }
@@ -77,5 +97,12 @@ describe("factories", () => {
         await expect(prisma.comment.count({ where: { postId: post2.id } })).resolves.toBe(1);
       });
     });
+
+    describe("trait and callback", () => {
+      test("Execute other factory in callback", async () => {
+        const { id: userId } = await UserFactory.use("withSelfCommentedPost").create();
+        await expect(prisma.comment.count({ where: { authorId: userId } })).resolves.toBe(1);
+      });
+    });
   });
 });
diff --git a/examples/example-prj/src/transient.test.ts b/examples/example-prj/src/transient.test.ts
new file mode 100644
index 0000000..4649260
--- /dev/null
+++ b/examples/example-prj/src/transient.test.ts
@@ -0,0 +1,29 @@
+import { defineUserFactory, defineLoginLogFactory } from "./__generated__/fabbrica";
+
+const prisma = jestPrisma.client;
+
+const LoginLogFactory = defineLoginLogFactory();
+
+const UserFactory = defineUserFactory.withTransientFields({
+  loginCount: 0,
+})({
+  onAfterCreate: async (user, { loginCount }) => {
+    await LoginLogFactory.createList(loginCount, { userId: user.id });
+  },
+});
+
+describe("factories", () => {
+  describe("UserFactory", () => {
+    test("callback with transient filed", async () => {
+      await UserFactory.create({ id: "user01", loginCount: 3 });
+
+      await expect(
+        prisma.loginLog.count({
+          where: {
+            userId: "user01",
+          },
+        }),
+      ).resolves.toBe(3);
+    });
+  });
+});
diff --git a/packages/artifact-testing/fixtures/field-variation/__generated__/fabbrica/index.ts b/packages/artifact-testing/fixtures/field-variation/__generated__/fabbrica/index.ts
index 260d151..11a8680 100644
--- a/packages/artifact-testing/fixtures/field-variation/__generated__/fabbrica/index.ts
+++ b/packages/artifact-testing/fixtures/field-variation/__generated__/fabbrica/index.ts
@@ -5,12 +5,20 @@ import type { NoPkModel } from "../client";
 import type { Role } from "../client";
 import type { Status } from "../client";
 import type { Prisma, PrismaClient } from "../client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -49,30 +57,36 @@ type UserFactoryDefineInput = {
     status?: Status | null;
 };
 
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
 
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface UserFactoryInterfaceWithoutTraits {
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
 }
 
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateUserScalarsOrEnums({ seq }: {
@@ -84,38 +98,57 @@ function autoGenerateUserScalarsOrEnums({ seq }: {
     };
 }
 
-function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): UserFactoryInterface<TOptions> {
+function defineUserFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends UserFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): UserFactoryInterface<TTransients, UserTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly UserTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("User", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: User) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.UserCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User" as const,
             build,
@@ -137,15 +170,22 @@ function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({
     };
 }
 
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link User} model.
  *
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> {
-    return defineUserFactoryInternal(options ?? {});
-}
+export const defineUserFactory = (<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> => {
+    return defineUserFactoryInternal(options ?? {}, {});
+}) as UserFactoryBuilder;
+
+defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type ComplexIdModelScalarOrEnumFields = {
     firstName: string;
@@ -157,30 +197,36 @@ type ComplexIdModelFactoryDefineInput = {
     lastName?: string;
 };
 
-type ComplexIdModelFactoryDefineOptions = {
-    defaultData?: Resolver<ComplexIdModelFactoryDefineInput, BuildDataOptions>;
+type ComplexIdModelTransientFields = Record<string, unknown> & Partial<Record<keyof ComplexIdModelFactoryDefineInput, never>>;
+
+type ComplexIdModelFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<ComplexIdModelFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<ComplexIdModel, Prisma.ComplexIdModelCreateInput, TTransients>;
+
+type ComplexIdModelFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<ComplexIdModelFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<ComplexIdModelFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: ComplexIdModelFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<ComplexIdModel, Prisma.ComplexIdModelCreateInput, TTransients>;
 
-type ComplexIdModelTraitKeys<TOptions extends ComplexIdModelFactoryDefineOptions> = keyof TOptions["traits"];
+type ComplexIdModelTraitKeys<TOptions extends ComplexIdModelFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface ComplexIdModelFactoryInterfaceWithoutTraits {
+export interface ComplexIdModelFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "ComplexIdModel";
-    build(inputData?: Partial<Prisma.ComplexIdModelCreateInput>): PromiseLike<Prisma.ComplexIdModelCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.ComplexIdModelCreateInput>): PromiseLike<Prisma.ComplexIdModelCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.ComplexIdModelCreateInput>[]): PromiseLike<Prisma.ComplexIdModelCreateInput[]>;
+    build(inputData?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<Prisma.ComplexIdModelCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<Prisma.ComplexIdModelCreateInput>;
+    buildList(list: readonly Partial<Prisma.ComplexIdModelCreateInput & TTransients>[]): PromiseLike<Prisma.ComplexIdModelCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<Prisma.ComplexIdModelCreateInput[]>;
     pickForConnect(inputData: ComplexIdModel): Pick<ComplexIdModel, "firstName" | "lastName">;
-    create(inputData?: Partial<Prisma.ComplexIdModelCreateInput>): PromiseLike<ComplexIdModel>;
-    createList(inputData: number | readonly Partial<Prisma.ComplexIdModelCreateInput>[]): PromiseLike<ComplexIdModel[]>;
-    createForConnect(inputData?: Partial<Prisma.ComplexIdModelCreateInput>): PromiseLike<Pick<ComplexIdModel, "firstName" | "lastName">>;
+    create(inputData?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<ComplexIdModel>;
+    createList(list: readonly Partial<Prisma.ComplexIdModelCreateInput & TTransients>[]): PromiseLike<ComplexIdModel[]>;
+    createList(count: number, item?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<ComplexIdModel[]>;
+    createForConnect(inputData?: Partial<Prisma.ComplexIdModelCreateInput & TTransients>): PromiseLike<Pick<ComplexIdModel, "firstName" | "lastName">>;
 }
 
-export interface ComplexIdModelFactoryInterface<TOptions extends ComplexIdModelFactoryDefineOptions = ComplexIdModelFactoryDefineOptions> extends ComplexIdModelFactoryInterfaceWithoutTraits {
-    use(name: ComplexIdModelTraitKeys<TOptions>, ...names: readonly ComplexIdModelTraitKeys<TOptions>[]): ComplexIdModelFactoryInterfaceWithoutTraits;
+export interface ComplexIdModelFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends ComplexIdModelFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): ComplexIdModelFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateComplexIdModelScalarsOrEnums({ seq }: {
@@ -192,39 +238,58 @@ function autoGenerateComplexIdModelScalarsOrEnums({ seq }: {
     };
 }
 
-function defineComplexIdModelFactoryInternal<TOptions extends ComplexIdModelFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): ComplexIdModelFactoryInterface<TOptions> {
+function defineComplexIdModelFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends ComplexIdModelFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): ComplexIdModelFactoryInterface<TTransients, ComplexIdModelTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly ComplexIdModelTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("ComplexIdModel", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.ComplexIdModelCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.ComplexIdModelCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateComplexIdModelScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<ComplexIdModelFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<ComplexIdModelFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<ComplexIdModelFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<ComplexIdModelFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.ComplexIdModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.ComplexIdModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.ComplexIdModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ComplexIdModelCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: ComplexIdModel) => ({
             firstName: inputData.firstName,
             lastName: inputData.lastName
         });
-        const create = async (inputData: Partial<Prisma.ComplexIdModelCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.ComplexIdModelCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().complexIdModel.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().complexIdModel.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.ComplexIdModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.ComplexIdModelCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ComplexIdModelCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.ComplexIdModelCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "ComplexIdModel" as const,
             build,
@@ -246,15 +311,22 @@ function defineComplexIdModelFactoryInternal<TOptions extends ComplexIdModelFact
     };
 }
 
+interface ComplexIdModelFactoryBuilder {
+    <TOptions extends ComplexIdModelFactoryDefineOptions>(options?: TOptions): ComplexIdModelFactoryInterface<{}, ComplexIdModelTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends ComplexIdModelTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends ComplexIdModelFactoryDefineOptions<TTransients>>(options?: TOptions) => ComplexIdModelFactoryInterface<TTransients, ComplexIdModelTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link ComplexIdModel} model.
  *
  * @param options
  * @returns factory {@link ComplexIdModelFactoryInterface}
  */
-export function defineComplexIdModelFactory<TOptions extends ComplexIdModelFactoryDefineOptions>(options?: TOptions): ComplexIdModelFactoryInterface<TOptions> {
-    return defineComplexIdModelFactoryInternal(options ?? {});
-}
+export const defineComplexIdModelFactory = (<TOptions extends ComplexIdModelFactoryDefineOptions>(options?: TOptions): ComplexIdModelFactoryInterface<TOptions> => {
+    return defineComplexIdModelFactoryInternal(options ?? {}, {});
+}) as ComplexIdModelFactoryBuilder;
+
+defineComplexIdModelFactory.withTransientFields = defaultTransientFieldValues => options => defineComplexIdModelFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type FieldTypePatternModelScalarOrEnumFields = {
     id: number;
@@ -290,30 +362,36 @@ type FieldTypePatternModelFactoryDefineInput = {
     nullableBigInt?: (bigint | number) | null;
 };
 
-type FieldTypePatternModelFactoryDefineOptions = {
-    defaultData?: Resolver<FieldTypePatternModelFactoryDefineInput, BuildDataOptions>;
+type FieldTypePatternModelTransientFields = Record<string, unknown> & Partial<Record<keyof FieldTypePatternModelFactoryDefineInput, never>>;
+
+type FieldTypePatternModelFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<FieldTypePatternModelFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<FieldTypePatternModel, Prisma.FieldTypePatternModelCreateInput, TTransients>;
+
+type FieldTypePatternModelFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<FieldTypePatternModelFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<FieldTypePatternModelFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: FieldTypePatternModelFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<FieldTypePatternModel, Prisma.FieldTypePatternModelCreateInput, TTransients>;
 
-type FieldTypePatternModelTraitKeys<TOptions extends FieldTypePatternModelFactoryDefineOptions> = keyof TOptions["traits"];
+type FieldTypePatternModelTraitKeys<TOptions extends FieldTypePatternModelFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface FieldTypePatternModelFactoryInterfaceWithoutTraits {
+export interface FieldTypePatternModelFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "FieldTypePatternModel";
-    build(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput>): PromiseLike<Prisma.FieldTypePatternModelCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput>): PromiseLike<Prisma.FieldTypePatternModelCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.FieldTypePatternModelCreateInput>[]): PromiseLike<Prisma.FieldTypePatternModelCreateInput[]>;
+    build(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<Prisma.FieldTypePatternModelCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<Prisma.FieldTypePatternModelCreateInput>;
+    buildList(list: readonly Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>[]): PromiseLike<Prisma.FieldTypePatternModelCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<Prisma.FieldTypePatternModelCreateInput[]>;
     pickForConnect(inputData: FieldTypePatternModel): Pick<FieldTypePatternModel, "id">;
-    create(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput>): PromiseLike<FieldTypePatternModel>;
-    createList(inputData: number | readonly Partial<Prisma.FieldTypePatternModelCreateInput>[]): PromiseLike<FieldTypePatternModel[]>;
-    createForConnect(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput>): PromiseLike<Pick<FieldTypePatternModel, "id">>;
+    create(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<FieldTypePatternModel>;
+    createList(list: readonly Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>[]): PromiseLike<FieldTypePatternModel[]>;
+    createList(count: number, item?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<FieldTypePatternModel[]>;
+    createForConnect(inputData?: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>): PromiseLike<Pick<FieldTypePatternModel, "id">>;
 }
 
-export interface FieldTypePatternModelFactoryInterface<TOptions extends FieldTypePatternModelFactoryDefineOptions = FieldTypePatternModelFactoryDefineOptions> extends FieldTypePatternModelFactoryInterfaceWithoutTraits {
-    use(name: FieldTypePatternModelTraitKeys<TOptions>, ...names: readonly FieldTypePatternModelTraitKeys<TOptions>[]): FieldTypePatternModelFactoryInterfaceWithoutTraits;
+export interface FieldTypePatternModelFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends FieldTypePatternModelFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): FieldTypePatternModelFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateFieldTypePatternModelScalarsOrEnums({ seq }: {
@@ -332,38 +410,57 @@ function autoGenerateFieldTypePatternModelScalarsOrEnums({ seq }: {
     };
 }
 
-function defineFieldTypePatternModelFactoryInternal<TOptions extends FieldTypePatternModelFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): FieldTypePatternModelFactoryInterface<TOptions> {
+function defineFieldTypePatternModelFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends FieldTypePatternModelFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): FieldTypePatternModelFactoryInterface<TTransients, FieldTypePatternModelTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly FieldTypePatternModelTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("FieldTypePatternModel", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.FieldTypePatternModelCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateFieldTypePatternModelScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<FieldTypePatternModelFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<FieldTypePatternModelFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<FieldTypePatternModelFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<FieldTypePatternModelFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.FieldTypePatternModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.FieldTypePatternModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.FieldTypePatternModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: FieldTypePatternModel) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.FieldTypePatternModelCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().fieldTypePatternModel.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().fieldTypePatternModel.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.FieldTypePatternModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.FieldTypePatternModelCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.FieldTypePatternModelCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.FieldTypePatternModelCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "FieldTypePatternModel" as const,
             build,
@@ -385,15 +482,22 @@ function defineFieldTypePatternModelFactoryInternal<TOptions extends FieldTypePa
     };
 }
 
+interface FieldTypePatternModelFactoryBuilder {
+    <TOptions extends FieldTypePatternModelFactoryDefineOptions>(options?: TOptions): FieldTypePatternModelFactoryInterface<{}, FieldTypePatternModelTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends FieldTypePatternModelTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends FieldTypePatternModelFactoryDefineOptions<TTransients>>(options?: TOptions) => FieldTypePatternModelFactoryInterface<TTransients, FieldTypePatternModelTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link FieldTypePatternModel} model.
  *
  * @param options
  * @returns factory {@link FieldTypePatternModelFactoryInterface}
  */
-export function defineFieldTypePatternModelFactory<TOptions extends FieldTypePatternModelFactoryDefineOptions>(options?: TOptions): FieldTypePatternModelFactoryInterface<TOptions> {
-    return defineFieldTypePatternModelFactoryInternal(options ?? {});
-}
+export const defineFieldTypePatternModelFactory = (<TOptions extends FieldTypePatternModelFactoryDefineOptions>(options?: TOptions): FieldTypePatternModelFactoryInterface<TOptions> => {
+    return defineFieldTypePatternModelFactoryInternal(options ?? {}, {});
+}) as FieldTypePatternModelFactoryBuilder;
+
+defineFieldTypePatternModelFactory.withTransientFields = defaultTransientFieldValues => options => defineFieldTypePatternModelFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type NoPkModelScalarOrEnumFields = {
     id: number;
@@ -403,30 +507,36 @@ type NoPkModelFactoryDefineInput = {
     id?: number;
 };
 
-type NoPkModelFactoryDefineOptions = {
-    defaultData?: Resolver<NoPkModelFactoryDefineInput, BuildDataOptions>;
+type NoPkModelTransientFields = Record<string, unknown> & Partial<Record<keyof NoPkModelFactoryDefineInput, never>>;
+
+type NoPkModelFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<NoPkModelFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<NoPkModel, Prisma.NoPkModelCreateInput, TTransients>;
+
+type NoPkModelFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<NoPkModelFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<NoPkModelFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: NoPkModelFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<NoPkModel, Prisma.NoPkModelCreateInput, TTransients>;
 
-type NoPkModelTraitKeys<TOptions extends NoPkModelFactoryDefineOptions> = keyof TOptions["traits"];
+type NoPkModelTraitKeys<TOptions extends NoPkModelFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface NoPkModelFactoryInterfaceWithoutTraits {
+export interface NoPkModelFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "NoPkModel";
-    build(inputData?: Partial<Prisma.NoPkModelCreateInput>): PromiseLike<Prisma.NoPkModelCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.NoPkModelCreateInput>): PromiseLike<Prisma.NoPkModelCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.NoPkModelCreateInput>[]): PromiseLike<Prisma.NoPkModelCreateInput[]>;
+    build(inputData?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<Prisma.NoPkModelCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<Prisma.NoPkModelCreateInput>;
+    buildList(list: readonly Partial<Prisma.NoPkModelCreateInput & TTransients>[]): PromiseLike<Prisma.NoPkModelCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<Prisma.NoPkModelCreateInput[]>;
     pickForConnect(inputData: NoPkModel): Pick<NoPkModel, "id">;
-    create(inputData?: Partial<Prisma.NoPkModelCreateInput>): PromiseLike<NoPkModel>;
-    createList(inputData: number | readonly Partial<Prisma.NoPkModelCreateInput>[]): PromiseLike<NoPkModel[]>;
-    createForConnect(inputData?: Partial<Prisma.NoPkModelCreateInput>): PromiseLike<Pick<NoPkModel, "id">>;
+    create(inputData?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<NoPkModel>;
+    createList(list: readonly Partial<Prisma.NoPkModelCreateInput & TTransients>[]): PromiseLike<NoPkModel[]>;
+    createList(count: number, item?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<NoPkModel[]>;
+    createForConnect(inputData?: Partial<Prisma.NoPkModelCreateInput & TTransients>): PromiseLike<Pick<NoPkModel, "id">>;
 }
 
-export interface NoPkModelFactoryInterface<TOptions extends NoPkModelFactoryDefineOptions = NoPkModelFactoryDefineOptions> extends NoPkModelFactoryInterfaceWithoutTraits {
-    use(name: NoPkModelTraitKeys<TOptions>, ...names: readonly NoPkModelTraitKeys<TOptions>[]): NoPkModelFactoryInterfaceWithoutTraits;
+export interface NoPkModelFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends NoPkModelFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): NoPkModelFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateNoPkModelScalarsOrEnums({ seq }: {
@@ -437,38 +547,57 @@ function autoGenerateNoPkModelScalarsOrEnums({ seq }: {
     };
 }
 
-function defineNoPkModelFactoryInternal<TOptions extends NoPkModelFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): NoPkModelFactoryInterface<TOptions> {
+function defineNoPkModelFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends NoPkModelFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): NoPkModelFactoryInterface<TTransients, NoPkModelTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly NoPkModelTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("NoPkModel", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.NoPkModelCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.NoPkModelCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateNoPkModelScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<NoPkModelFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<NoPkModelFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<NoPkModelFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<NoPkModelFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.NoPkModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.NoPkModelCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.NoPkModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.NoPkModelCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: NoPkModel) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.NoPkModelCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.NoPkModelCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().noPkModel.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().noPkModel.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.NoPkModelCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.NoPkModelCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.NoPkModelCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.NoPkModelCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "NoPkModel" as const,
             build,
@@ -490,12 +619,19 @@ function defineNoPkModelFactoryInternal<TOptions extends NoPkModelFactoryDefineO
     };
 }
 
+interface NoPkModelFactoryBuilder {
+    <TOptions extends NoPkModelFactoryDefineOptions>(options?: TOptions): NoPkModelFactoryInterface<{}, NoPkModelTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends NoPkModelTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends NoPkModelFactoryDefineOptions<TTransients>>(options?: TOptions) => NoPkModelFactoryInterface<TTransients, NoPkModelTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link NoPkModel} model.
  *
  * @param options
  * @returns factory {@link NoPkModelFactoryInterface}
  */
-export function defineNoPkModelFactory<TOptions extends NoPkModelFactoryDefineOptions>(options?: TOptions): NoPkModelFactoryInterface<TOptions> {
-    return defineNoPkModelFactoryInternal(options ?? {});
-}
+export const defineNoPkModelFactory = (<TOptions extends NoPkModelFactoryDefineOptions>(options?: TOptions): NoPkModelFactoryInterface<TOptions> => {
+    return defineNoPkModelFactoryInternal(options ?? {}, {});
+}) as NoPkModelFactoryBuilder;
+
+defineNoPkModelFactory.withTransientFields = defaultTransientFieldValues => options => defineNoPkModelFactoryInternal(options ?? {}, defaultTransientFieldValues);
diff --git a/packages/artifact-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts b/packages/artifact-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts
index feb8dff..77fffb0 100644
--- a/packages/artifact-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts
+++ b/packages/artifact-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts
@@ -1,12 +1,20 @@
 import type { Post } from "../client";
 import type { Category } from "../client";
 import type { Prisma, PrismaClient } from "../client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -42,30 +50,36 @@ type PostFactoryDefineInput = {
     categories?: Prisma.CategoryCreateNestedManyWithoutPostsInput;
 };
 
-type PostFactoryDefineOptions = {
-    defaultData?: Resolver<PostFactoryDefineInput, BuildDataOptions>;
+type PostTransientFields = Record<string, unknown> & Partial<Record<keyof PostFactoryDefineInput, never>>;
+
+type PostFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
+
+type PostFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<PostFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: PostFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
 
-type PostTraitKeys<TOptions extends PostFactoryDefineOptions> = keyof TOptions["traits"];
+type PostTraitKeys<TOptions extends PostFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface PostFactoryInterfaceWithoutTraits {
+export interface PostFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Post";
-    build(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    build(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput[]>;
     pickForConnect(inputData: Post): Pick<Post, "id">;
-    create(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Post>;
-    createList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Post[]>;
-    createForConnect(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Pick<Post, "id">>;
+    create(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post>;
+    createList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Post[]>;
+    createList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post[]>;
+    createForConnect(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Pick<Post, "id">>;
 }
 
-export interface PostFactoryInterface<TOptions extends PostFactoryDefineOptions = PostFactoryDefineOptions> extends PostFactoryInterfaceWithoutTraits {
-    use(name: PostTraitKeys<TOptions>, ...names: readonly PostTraitKeys<TOptions>[]): PostFactoryInterfaceWithoutTraits;
+export interface PostFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends PostFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): PostFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGeneratePostScalarsOrEnums({ seq }: {
@@ -77,38 +91,57 @@ function autoGeneratePostScalarsOrEnums({ seq }: {
     };
 }
 
-function definePostFactoryInternal<TOptions extends PostFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): PostFactoryInterface<TOptions> {
+function definePostFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends PostFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): PostFactoryInterface<TTransients, PostTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly PostTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("Post", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.PostCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<PostFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<PostFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<PostFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<PostFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.PostCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.PostCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.PostCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.PostCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: Post) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.PostCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().post.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().post.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.PostCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.PostCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.PostCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Post" as const,
             build,
@@ -130,15 +163,22 @@ function definePostFactoryInternal<TOptions extends PostFactoryDefineOptions>({
     };
 }
 
+interface PostFactoryBuilder {
+    <TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<{}, PostTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends PostTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends PostFactoryDefineOptions<TTransients>>(options?: TOptions) => PostFactoryInterface<TTransients, PostTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link Post} model.
  *
  * @param options
  * @returns factory {@link PostFactoryInterface}
  */
-export function definePostFactory<TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<TOptions> {
-    return definePostFactoryInternal(options ?? {});
-}
+export const definePostFactory = (<TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<TOptions> => {
+    return definePostFactoryInternal(options ?? {}, {});
+}) as PostFactoryBuilder;
+
+definePostFactory.withTransientFields = defaultTransientFieldValues => options => definePostFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type CategoryScalarOrEnumFields = {
     id: string;
@@ -151,30 +191,36 @@ type CategoryFactoryDefineInput = {
     posts?: Prisma.PostCreateNestedManyWithoutCategoriesInput;
 };
 
-type CategoryFactoryDefineOptions = {
-    defaultData?: Resolver<CategoryFactoryDefineInput, BuildDataOptions>;
+type CategoryTransientFields = Record<string, unknown> & Partial<Record<keyof CategoryFactoryDefineInput, never>>;
+
+type CategoryFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Category, Prisma.CategoryCreateInput, TTransients>;
+
+type CategoryFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<CategoryFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: CategoryFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<Category, Prisma.CategoryCreateInput, TTransients>;
 
-type CategoryTraitKeys<TOptions extends CategoryFactoryDefineOptions> = keyof TOptions["traits"];
+type CategoryTraitKeys<TOptions extends CategoryFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface CategoryFactoryInterfaceWithoutTraits {
+export interface CategoryFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Category";
-    build(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Prisma.CategoryCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Prisma.CategoryCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]): PromiseLike<Prisma.CategoryCreateInput[]>;
+    build(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput>;
+    buildList(list: readonly Partial<Prisma.CategoryCreateInput & TTransients>[]): PromiseLike<Prisma.CategoryCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Prisma.CategoryCreateInput[]>;
     pickForConnect(inputData: Category): Pick<Category, "id">;
-    create(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Category>;
-    createList(inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]): PromiseLike<Category[]>;
-    createForConnect(inputData?: Partial<Prisma.CategoryCreateInput>): PromiseLike<Pick<Category, "id">>;
+    create(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Category>;
+    createList(list: readonly Partial<Prisma.CategoryCreateInput & TTransients>[]): PromiseLike<Category[]>;
+    createList(count: number, item?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Category[]>;
+    createForConnect(inputData?: Partial<Prisma.CategoryCreateInput & TTransients>): PromiseLike<Pick<Category, "id">>;
 }
 
-export interface CategoryFactoryInterface<TOptions extends CategoryFactoryDefineOptions = CategoryFactoryDefineOptions> extends CategoryFactoryInterfaceWithoutTraits {
-    use(name: CategoryTraitKeys<TOptions>, ...names: readonly CategoryTraitKeys<TOptions>[]): CategoryFactoryInterfaceWithoutTraits;
+export interface CategoryFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends CategoryFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): CategoryFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateCategoryScalarsOrEnums({ seq }: {
@@ -186,38 +232,57 @@ function autoGenerateCategoryScalarsOrEnums({ seq }: {
     };
 }
 
-function defineCategoryFactoryInternal<TOptions extends CategoryFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): CategoryFactoryInterface<TOptions> {
+function defineCategoryFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends CategoryFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): CategoryFactoryInterface<TTransients, CategoryTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly CategoryTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("Category", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.CategoryCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.CategoryCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateCategoryScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<CategoryFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<CategoryFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<CategoryFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.CategoryCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.CategoryCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.CategoryCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: Category) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.CategoryCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.CategoryCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().category.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().category.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.CategoryCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.CategoryCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.CategoryCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.CategoryCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Category" as const,
             build,
@@ -239,12 +304,19 @@ function defineCategoryFactoryInternal<TOptions extends CategoryFactoryDefineOpt
     };
 }
 
+interface CategoryFactoryBuilder {
+    <TOptions extends CategoryFactoryDefineOptions>(options?: TOptions): CategoryFactoryInterface<{}, CategoryTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends CategoryTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends CategoryFactoryDefineOptions<TTransients>>(options?: TOptions) => CategoryFactoryInterface<TTransients, CategoryTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link Category} model.
  *
  * @param options
  * @returns factory {@link CategoryFactoryInterface}
  */
-export function defineCategoryFactory<TOptions extends CategoryFactoryDefineOptions>(options?: TOptions): CategoryFactoryInterface<TOptions> {
-    return defineCategoryFactoryInternal(options ?? {});
-}
+export const defineCategoryFactory = (<TOptions extends CategoryFactoryDefineOptions>(options?: TOptions): CategoryFactoryInterface<TOptions> => {
+    return defineCategoryFactoryInternal(options ?? {}, {});
+}) as CategoryFactoryBuilder;
+
+defineCategoryFactory.withTransientFields = defaultTransientFieldValues => options => defineCategoryFactoryInternal(options ?? {}, defaultTransientFieldValues);
diff --git a/packages/artifact-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts b/packages/artifact-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts
index 1304623..5320a00 100644
--- a/packages/artifact-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts
+++ b/packages/artifact-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts
@@ -2,12 +2,20 @@ import type { User } from "../client";
 import type { Post } from "../client";
 import type { Review } from "../client";
 import type { Prisma, PrismaClient } from "../client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -63,30 +71,36 @@ type UserFactoryDefineInput = {
     reviews?: Prisma.ReviewCreateNestedManyWithoutReviewerInput;
 };
 
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
 
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface UserFactoryInterfaceWithoutTraits {
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
 }
 
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateUserScalarsOrEnums({ seq }: {
@@ -98,38 +112,57 @@ function autoGenerateUserScalarsOrEnums({ seq }: {
     };
 }
 
-function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): UserFactoryInterface<TOptions> {
+function defineUserFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends UserFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): UserFactoryInterface<TTransients, UserTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly UserTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("User", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: User) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.UserCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User" as const,
             build,
@@ -151,15 +184,22 @@ function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({
     };
 }
 
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link User} model.
  *
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> {
-    return defineUserFactoryInternal(options ?? {});
-}
+export const defineUserFactory = (<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> => {
+    return defineUserFactoryInternal(options ?? {}, {});
+}) as UserFactoryBuilder;
+
+defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type PostScalarOrEnumFields = {
     id: string;
@@ -178,34 +218,40 @@ type PostFactoryDefineInput = {
     reviews?: Prisma.ReviewCreateNestedManyWithoutPostInput;
 };
 
-type PostFactoryDefineOptions = {
-    defaultData?: Resolver<PostFactoryDefineInput, BuildDataOptions>;
+type PostTransientFields = Record<string, unknown> & Partial<Record<keyof PostFactoryDefineInput, never>>;
+
+type PostFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
+
+type PostFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<PostFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<PostFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: PostFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<Post, Prisma.PostCreateInput, TTransients>;
 
 function isPostauthorFactory(x: PostauthorFactory | Prisma.UserCreateNestedOneWithoutPostsInput | undefined): x is PostauthorFactory {
     return (x as any)?._factoryFor === "User";
 }
 
-type PostTraitKeys<TOptions extends PostFactoryDefineOptions> = keyof TOptions["traits"];
+type PostTraitKeys<TOptions extends PostFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface PostFactoryInterfaceWithoutTraits {
+export interface PostFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Post";
-    build(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Prisma.PostCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    build(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput>;
+    buildList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Prisma.PostCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Prisma.PostCreateInput[]>;
     pickForConnect(inputData: Post): Pick<Post, "id">;
-    create(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Post>;
-    createList(inputData: number | readonly Partial<Prisma.PostCreateInput>[]): PromiseLike<Post[]>;
-    createForConnect(inputData?: Partial<Prisma.PostCreateInput>): PromiseLike<Pick<Post, "id">>;
+    create(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post>;
+    createList(list: readonly Partial<Prisma.PostCreateInput & TTransients>[]): PromiseLike<Post[]>;
+    createList(count: number, item?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Post[]>;
+    createForConnect(inputData?: Partial<Prisma.PostCreateInput & TTransients>): PromiseLike<Pick<Post, "id">>;
 }
 
-export interface PostFactoryInterface<TOptions extends PostFactoryDefineOptions = PostFactoryDefineOptions> extends PostFactoryInterfaceWithoutTraits {
-    use(name: PostTraitKeys<TOptions>, ...names: readonly PostTraitKeys<TOptions>[]): PostFactoryInterfaceWithoutTraits;
+export interface PostFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends PostFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): PostFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGeneratePostScalarsOrEnums({ seq }: {
@@ -217,42 +263,61 @@ function autoGeneratePostScalarsOrEnums({ seq }: {
     };
 }
 
-function definePostFactoryInternal<TOptions extends PostFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): PostFactoryInterface<TOptions> {
+function definePostFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends PostFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): PostFactoryInterface<TTransients, PostTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly PostTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("Post", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.PostCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<PostFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<PostFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<PostFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<PostFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 author: isPostauthorFactory(defaultData.author) ? {
                     create: await defaultData.author.build()
                 } : defaultData.author
             };
-            const data: Prisma.PostCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.PostCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.PostCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.PostCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: Post) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.PostCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().post.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().post.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.PostCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.PostCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.PostCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.PostCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Post" as const,
             build,
@@ -274,15 +339,22 @@ function definePostFactoryInternal<TOptions extends PostFactoryDefineOptions>({
     };
 }
 
+interface PostFactoryBuilder {
+    <TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<{}, PostTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends PostTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends PostFactoryDefineOptions<TTransients>>(options?: TOptions) => PostFactoryInterface<TTransients, PostTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link Post} model.
  *
  * @param options
  * @returns factory {@link PostFactoryInterface}
  */
-export function definePostFactory<TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<TOptions> {
-    return definePostFactoryInternal(options ?? {});
-}
+export const definePostFactory = (<TOptions extends PostFactoryDefineOptions>(options?: TOptions): PostFactoryInterface<TOptions> => {
+    return definePostFactoryInternal(options ?? {}, {});
+}) as PostFactoryBuilder;
+
+definePostFactory.withTransientFields = defaultTransientFieldValues => options => definePostFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type ReviewScalarOrEnumFields = {
     id: string;
@@ -306,14 +378,18 @@ type ReviewFactoryDefineInput = {
     reviewer: ReviewreviewerFactory | Prisma.UserCreateNestedOneWithoutReviewsInput;
 };
 
-type ReviewFactoryDefineOptions = {
-    defaultData: Resolver<ReviewFactoryDefineInput, BuildDataOptions>;
+type ReviewTransientFields = Record<string, unknown> & Partial<Record<keyof ReviewFactoryDefineInput, never>>;
+
+type ReviewFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<ReviewFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Review, Prisma.ReviewCreateInput, TTransients>;
+
+type ReviewFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData: Resolver<ReviewFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<ReviewFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: string | symbol]: ReviewFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<Review, Prisma.ReviewCreateInput, TTransients>;
 
 function isReviewpostFactory(x: ReviewpostFactory | Prisma.PostCreateNestedOneWithoutReviewsInput | undefined): x is ReviewpostFactory {
     return (x as any)?._factoryFor === "Post";
@@ -323,21 +399,23 @@ function isReviewreviewerFactory(x: ReviewreviewerFactory | Prisma.UserCreateNes
     return (x as any)?._factoryFor === "User";
 }
 
-type ReviewTraitKeys<TOptions extends ReviewFactoryDefineOptions> = keyof TOptions["traits"];
+type ReviewTraitKeys<TOptions extends ReviewFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface ReviewFactoryInterfaceWithoutTraits {
+export interface ReviewFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Review";
-    build(inputData?: Partial<Prisma.ReviewCreateInput>): PromiseLike<Prisma.ReviewCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.ReviewCreateInput>): PromiseLike<Prisma.ReviewCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.ReviewCreateInput>[]): PromiseLike<Prisma.ReviewCreateInput[]>;
+    build(inputData?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Prisma.ReviewCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Prisma.ReviewCreateInput>;
+    buildList(list: readonly Partial<Prisma.ReviewCreateInput & TTransients>[]): PromiseLike<Prisma.ReviewCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Prisma.ReviewCreateInput[]>;
     pickForConnect(inputData: Review): Pick<Review, "id">;
-    create(inputData?: Partial<Prisma.ReviewCreateInput>): PromiseLike<Review>;
-    createList(inputData: number | readonly Partial<Prisma.ReviewCreateInput>[]): PromiseLike<Review[]>;
-    createForConnect(inputData?: Partial<Prisma.ReviewCreateInput>): PromiseLike<Pick<Review, "id">>;
+    create(inputData?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Review>;
+    createList(list: readonly Partial<Prisma.ReviewCreateInput & TTransients>[]): PromiseLike<Review[]>;
+    createList(count: number, item?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Review[]>;
+    createForConnect(inputData?: Partial<Prisma.ReviewCreateInput & TTransients>): PromiseLike<Pick<Review, "id">>;
 }
 
-export interface ReviewFactoryInterface<TOptions extends ReviewFactoryDefineOptions = ReviewFactoryDefineOptions> extends ReviewFactoryInterfaceWithoutTraits {
-    use(name: ReviewTraitKeys<TOptions>, ...names: readonly ReviewTraitKeys<TOptions>[]): ReviewFactoryInterfaceWithoutTraits;
+export interface ReviewFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends ReviewFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): ReviewFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateReviewScalarsOrEnums({ seq }: {
@@ -349,24 +427,38 @@ function autoGenerateReviewScalarsOrEnums({ seq }: {
     };
 }
 
-function defineReviewFactoryInternal<TOptions extends ReviewFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): ReviewFactoryInterface<TOptions> {
+function defineReviewFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends ReviewFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): ReviewFactoryInterface<TTransients, ReviewTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly ReviewTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("Review", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.ReviewCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.ReviewCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateReviewScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<ReviewFactoryDefineInput, BuildDataOptions>(defaultDataResolver);
+            const resolveValue = normalizeResolver<ReviewFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver);
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<ReviewFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<ReviewFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 post: isReviewpostFactory(defaultData.post) ? {
                     create: await defaultData.post.build()
@@ -375,19 +467,24 @@ function defineReviewFactoryInternal<TOptions extends ReviewFactoryDefineOptions
                     create: await defaultData.reviewer.build()
                 } : defaultData.reviewer
             };
-            const data: Prisma.ReviewCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.ReviewCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.ReviewCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ReviewCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: Review) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.ReviewCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.ReviewCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().review.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().review.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.ReviewCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.ReviewCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ReviewCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.ReviewCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Review" as const,
             build,
@@ -409,12 +506,19 @@ function defineReviewFactoryInternal<TOptions extends ReviewFactoryDefineOptions
     };
 }
 
+interface ReviewFactoryBuilder {
+    <TOptions extends ReviewFactoryDefineOptions>(options: TOptions): ReviewFactoryInterface<{}, ReviewTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends ReviewTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends ReviewFactoryDefineOptions<TTransients>>(options: TOptions) => ReviewFactoryInterface<TTransients, ReviewTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link Review} model.
  *
  * @param options
  * @returns factory {@link ReviewFactoryInterface}
  */
-export function defineReviewFactory<TOptions extends ReviewFactoryDefineOptions>(options: TOptions): ReviewFactoryInterface<TOptions> {
-    return defineReviewFactoryInternal(options);
-}
+export const defineReviewFactory = (<TOptions extends ReviewFactoryDefineOptions>(options: TOptions): ReviewFactoryInterface<TOptions> => {
+    return defineReviewFactoryInternal(options, {});
+}) as ReviewFactoryBuilder;
+
+defineReviewFactory.withTransientFields = defaultTransientFieldValues => options => defineReviewFactoryInternal(options, defaultTransientFieldValues);
diff --git a/packages/artifact-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts b/packages/artifact-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts
index fd70d67..b9e2a7c 100644
--- a/packages/artifact-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts
+++ b/packages/artifact-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts
@@ -1,12 +1,20 @@
 import type { User } from "../client";
 import type { Profile } from "../client";
 import type { Prisma, PrismaClient } from "../client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -47,34 +55,40 @@ type UserFactoryDefineInput = {
     profile?: UserprofileFactory | Prisma.ProfileCreateNestedOneWithoutUserInput;
 };
 
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
 
 function isUserprofileFactory(x: UserprofileFactory | Prisma.ProfileCreateNestedOneWithoutUserInput | undefined): x is UserprofileFactory {
     return (x as any)?._factoryFor === "Profile";
 }
 
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface UserFactoryInterfaceWithoutTraits {
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
 }
 
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateUserScalarsOrEnums({ seq }: {
@@ -86,42 +100,61 @@ function autoGenerateUserScalarsOrEnums({ seq }: {
     };
 }
 
-function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): UserFactoryInterface<TOptions> {
+function defineUserFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends UserFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): UserFactoryInterface<TTransients, UserTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly UserTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("User", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 profile: isUserprofileFactory(defaultData.profile) ? {
                     create: await defaultData.profile.build()
                 } : defaultData.profile
             };
-            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: User) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.UserCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User" as const,
             build,
@@ -143,15 +176,22 @@ function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({
     };
 }
 
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link User} model.
  *
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> {
-    return defineUserFactoryInternal(options ?? {});
-}
+export const defineUserFactory = (<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> => {
+    return defineUserFactoryInternal(options ?? {}, {});
+}) as UserFactoryBuilder;
+
+defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
 
 type ProfileScalarOrEnumFields = {
     id: string;
@@ -167,34 +207,40 @@ type ProfileFactoryDefineInput = {
     user: ProfileuserFactory | Prisma.UserCreateNestedOneWithoutProfileInput;
 };
 
-type ProfileFactoryDefineOptions = {
-    defaultData: Resolver<ProfileFactoryDefineInput, BuildDataOptions>;
+type ProfileTransientFields = Record<string, unknown> & Partial<Record<keyof ProfileFactoryDefineInput, never>>;
+
+type ProfileFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<ProfileFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<Profile, Prisma.ProfileCreateInput, TTransients>;
+
+type ProfileFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData: Resolver<ProfileFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<ProfileFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: string | symbol]: ProfileFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<Profile, Prisma.ProfileCreateInput, TTransients>;
 
 function isProfileuserFactory(x: ProfileuserFactory | Prisma.UserCreateNestedOneWithoutProfileInput | undefined): x is ProfileuserFactory {
     return (x as any)?._factoryFor === "User";
 }
 
-type ProfileTraitKeys<TOptions extends ProfileFactoryDefineOptions> = keyof TOptions["traits"];
+type ProfileTraitKeys<TOptions extends ProfileFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface ProfileFactoryInterfaceWithoutTraits {
+export interface ProfileFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "Profile";
-    build(inputData?: Partial<Prisma.ProfileCreateInput>): PromiseLike<Prisma.ProfileCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.ProfileCreateInput>): PromiseLike<Prisma.ProfileCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.ProfileCreateInput>[]): PromiseLike<Prisma.ProfileCreateInput[]>;
+    build(inputData?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Prisma.ProfileCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Prisma.ProfileCreateInput>;
+    buildList(list: readonly Partial<Prisma.ProfileCreateInput & TTransients>[]): PromiseLike<Prisma.ProfileCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Prisma.ProfileCreateInput[]>;
     pickForConnect(inputData: Profile): Pick<Profile, "id">;
-    create(inputData?: Partial<Prisma.ProfileCreateInput>): PromiseLike<Profile>;
-    createList(inputData: number | readonly Partial<Prisma.ProfileCreateInput>[]): PromiseLike<Profile[]>;
-    createForConnect(inputData?: Partial<Prisma.ProfileCreateInput>): PromiseLike<Pick<Profile, "id">>;
+    create(inputData?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Profile>;
+    createList(list: readonly Partial<Prisma.ProfileCreateInput & TTransients>[]): PromiseLike<Profile[]>;
+    createList(count: number, item?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Profile[]>;
+    createForConnect(inputData?: Partial<Prisma.ProfileCreateInput & TTransients>): PromiseLike<Pick<Profile, "id">>;
 }
 
-export interface ProfileFactoryInterface<TOptions extends ProfileFactoryDefineOptions = ProfileFactoryDefineOptions> extends ProfileFactoryInterfaceWithoutTraits {
-    use(name: ProfileTraitKeys<TOptions>, ...names: readonly ProfileTraitKeys<TOptions>[]): ProfileFactoryInterfaceWithoutTraits;
+export interface ProfileFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends ProfileFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): ProfileFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateProfileScalarsOrEnums({ seq }: {
@@ -205,42 +251,61 @@ function autoGenerateProfileScalarsOrEnums({ seq }: {
     };
 }
 
-function defineProfileFactoryInternal<TOptions extends ProfileFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): ProfileFactoryInterface<TOptions> {
+function defineProfileFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends ProfileFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): ProfileFactoryInterface<TTransients, ProfileTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly ProfileTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("Profile", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.ProfileCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.ProfileCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateProfileScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<ProfileFactoryDefineInput, BuildDataOptions>(defaultDataResolver);
+            const resolveValue = normalizeResolver<ProfileFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver);
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<ProfileFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<ProfileFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {
                 user: isProfileuserFactory(defaultData.user) ? {
                     create: await defaultData.user.build()
                 } : defaultData.user
             };
-            const data: Prisma.ProfileCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.ProfileCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.ProfileCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ProfileCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: Profile) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.ProfileCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.ProfileCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().profile.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().profile.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.ProfileCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.ProfileCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.ProfileCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.ProfileCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "Profile" as const,
             build,
@@ -262,12 +327,19 @@ function defineProfileFactoryInternal<TOptions extends ProfileFactoryDefineOptio
     };
 }
 
+interface ProfileFactoryBuilder {
+    <TOptions extends ProfileFactoryDefineOptions>(options: TOptions): ProfileFactoryInterface<{}, ProfileTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends ProfileTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends ProfileFactoryDefineOptions<TTransients>>(options: TOptions) => ProfileFactoryInterface<TTransients, ProfileTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link Profile} model.
  *
  * @param options
  * @returns factory {@link ProfileFactoryInterface}
  */
-export function defineProfileFactory<TOptions extends ProfileFactoryDefineOptions>(options: TOptions): ProfileFactoryInterface<TOptions> {
-    return defineProfileFactoryInternal(options);
-}
+export const defineProfileFactory = (<TOptions extends ProfileFactoryDefineOptions>(options: TOptions): ProfileFactoryInterface<TOptions> => {
+    return defineProfileFactoryInternal(options, {});
+}) as ProfileFactoryBuilder;
+
+defineProfileFactory.withTransientFields = defaultTransientFieldValues => options => defineProfileFactoryInternal(options, defaultTransientFieldValues);
diff --git a/packages/artifact-testing/fixtures/simple-model/__generated__/fabbrica/index.ts b/packages/artifact-testing/fixtures/simple-model/__generated__/fabbrica/index.ts
index 538b6c9..e96470b 100644
--- a/packages/artifact-testing/fixtures/simple-model/__generated__/fabbrica/index.ts
+++ b/packages/artifact-testing/fixtures/simple-model/__generated__/fabbrica/index.ts
@@ -1,11 +1,19 @@
 import type { User } from "../client";
 import type { Prisma, PrismaClient } from "../client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -29,30 +37,36 @@ type UserFactoryDefineInput = {
     name?: string;
 };
 
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
 
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface UserFactoryInterfaceWithoutTraits {
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
 }
 
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateUserScalarsOrEnums({ seq }: {
@@ -64,38 +78,57 @@ function autoGenerateUserScalarsOrEnums({ seq }: {
     };
 }
 
-function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): UserFactoryInterface<TOptions> {
+function defineUserFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends UserFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): UserFactoryInterface<TTransients, UserTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly UserTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("User", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: User) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.UserCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User" as const,
             build,
@@ -117,12 +150,19 @@ function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({
     };
 }
 
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link User} model.
  *
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> {
-    return defineUserFactoryInternal(options ?? {});
-}
+export const defineUserFactory = (<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> => {
+    return defineUserFactoryInternal(options ?? {}, {});
+}) as UserFactoryBuilder;
+
+defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
diff --git a/packages/artifact-testing/fixtures/simple-model/callbacks.test.ts b/packages/artifact-testing/fixtures/simple-model/callbacks.test.ts
new file mode 100644
index 0000000..efd750f
--- /dev/null
+++ b/packages/artifact-testing/fixtures/simple-model/callbacks.test.ts
@@ -0,0 +1,157 @@
+import type { PrismaClient, User } from "./__generated__/client";
+
+import { initialize, defineUserFactory } from "./__generated__/fabbrica";
+
+describe("Generated functions", () => {
+  beforeAll(() => {
+    const clientStub = {
+      user: { create: jest.fn().mockReturnValue({ id: "stub id", name: "stub name" } as User) },
+    } as unknown as PrismaClient;
+    initialize({ prisma: clientStub });
+  });
+
+  describe("callback", () => {
+    test("onAfterBuild", async () => {
+      const mock = jest.fn();
+      const UserFactory = defineUserFactory({
+        onAfterBuild: user => {
+          mock(user);
+        },
+      });
+
+      await UserFactory.build({ id: "id", name: "name" });
+
+      expect(mock).toBeCalledTimes(1);
+      expect(mock).toBeCalledWith({ id: "id", name: "name" });
+    });
+
+    test("onBeforeCreate", async () => {
+      const mock = jest.fn();
+      const UserFactory = defineUserFactory({
+        onBeforeCreate: user => {
+          mock(user);
+        },
+      });
+
+      await UserFactory.create({ id: "id", name: "name" });
+
+      expect(mock).toBeCalledTimes(1);
+      expect(mock).toBeCalledWith({ id: "id", name: "name" });
+    });
+
+    test("onAfterCreate", async () => {
+      const mock = jest.fn();
+      const UserFactory = defineUserFactory({
+        onAfterCreate: user => {
+          mock(user);
+        },
+      });
+
+      await UserFactory.create();
+
+      expect(mock).toBeCalledTimes(1);
+      expect(mock).toBeCalledWith({ id: "stub id", name: "stub name" });
+    });
+
+    test("callback orders with traits", async () => {
+      const mock = jest.fn();
+      const UserFactory = defineUserFactory({
+        onAfterBuild: () => {
+          mock("factory default", "onAfterBuild");
+        },
+        onBeforeCreate: () => {
+          mock("factory default", "onBeforeCreate");
+        },
+        onAfterCreate: () => {
+          mock("factory default", "onAfterCreate");
+        },
+        traits: {
+          a: {
+            onAfterBuild: () => {
+              mock("trait a", "onAfterBuild");
+            },
+            onBeforeCreate: () => {
+              mock("trait a", "onBeforeCreate");
+            },
+            onAfterCreate: () => {
+              mock("trait a", "onAfterCreate");
+            },
+          },
+          b: {
+            onAfterBuild: () => {
+              mock("trait b", "onAfterBuild");
+            },
+            onBeforeCreate: () => {
+              mock("trait b", "onBeforeCreate");
+            },
+            onAfterCreate: () => {
+              mock("trait b", "onAfterCreate");
+            },
+          },
+        },
+      });
+
+      await UserFactory.use("a", "b").create();
+
+      expect(mock).toHaveBeenNthCalledWith(1, "factory default", "onAfterBuild");
+      expect(mock).toHaveBeenNthCalledWith(2, "trait a", "onAfterBuild");
+      expect(mock).toHaveBeenNthCalledWith(3, "trait b", "onAfterBuild");
+      expect(mock).toHaveBeenNthCalledWith(4, "trait b", "onBeforeCreate");
+      expect(mock).toHaveBeenNthCalledWith(5, "trait a", "onBeforeCreate");
+      expect(mock).toHaveBeenNthCalledWith(6, "factory default", "onBeforeCreate");
+      expect(mock).toHaveBeenNthCalledWith(7, "factory default", "onAfterCreate");
+      expect(mock).toHaveBeenNthCalledWith(8, "trait a", "onAfterCreate");
+      expect(mock).toHaveBeenNthCalledWith(9, "trait b", "onAfterCreate");
+    });
+
+    describe("callbacks with transient fields", () => {
+      test("onAfterBuild", async () => {
+        const mock = jest.fn();
+        const UserFactory = defineUserFactory.withTransientFields({
+          hoge: 0,
+        })({
+          onAfterBuild: (_, { hoge }) => {
+            mock(hoge);
+          },
+        });
+
+        await UserFactory.build({ hoge: 100 });
+
+        expect(mock).toBeCalledTimes(1);
+        expect(mock).toBeCalledWith(100);
+      });
+
+      test("onBeforeCreate", async () => {
+        const mock = jest.fn();
+        const UserFactory = defineUserFactory.withTransientFields({
+          hoge: 0,
+        })({
+          onBeforeCreate: (_, { hoge }) => {
+            mock(hoge);
+          },
+        });
+
+        await UserFactory.create({ hoge: 100 });
+
+        expect(mock).toBeCalledTimes(1);
+        expect(mock).toBeCalledWith(100);
+      });
+
+      test("onAfterCreate", async () => {
+        const mock = jest.fn();
+        const UserFactory = defineUserFactory.withTransientFields({
+          hoge: 0,
+        })({
+          onAfterCreate: (_, { hoge }) => {
+            mock(hoge);
+          },
+        });
+
+        await UserFactory.create({ hoge: 100 });
+
+        expect(mock).toBeCalledTimes(1);
+        expect(mock).toBeCalledWith(100);
+      });
+    });
+  });
+});
diff --git a/packages/artifact-testing/fixtures/simple-model/traits.test.ts b/packages/artifact-testing/fixtures/simple-model/traits.test.ts
new file mode 100644
index 0000000..2c04704
--- /dev/null
+++ b/packages/artifact-testing/fixtures/simple-model/traits.test.ts
@@ -0,0 +1,46 @@
+import { defineUserFactory } from "./__generated__/fabbrica";
+
+describe("traits", () => {
+  test("override default data", async () => {
+    const UserFactory = defineUserFactory({
+      defaultData: {
+        name: "default",
+      },
+      traits: {
+        a: {
+          data: {
+            name: "trait a",
+          },
+        },
+        b: {
+          data: {
+            name: "trait b",
+          },
+        },
+      },
+    });
+
+    await expect(UserFactory.build()).resolves.toMatchObject({ name: "default" });
+    await expect(UserFactory.use("a").build()).resolves.toMatchObject({ name: "trait a" });
+    await expect(UserFactory.use("b").build()).resolves.toMatchObject({ name: "trait b" });
+    await expect(UserFactory.use("a", "b").build()).resolves.toMatchObject({ name: "trait b" });
+    await expect(UserFactory.use("b", "a").build()).resolves.toMatchObject({ name: "trait a" });
+  });
+
+  test("use transient fields from trait", async () => {
+    const UserFactory = defineUserFactory.withTransientFields({
+      hoge: 0,
+    })({
+      defaultData: {
+        name: "default",
+      },
+      traits: {
+        myTrait: {
+          data: ({ hoge }) => ({ name: `user${hoge}` }),
+        },
+      },
+    });
+
+    await expect(UserFactory.use("myTrait").build({ hoge: 1 })).resolves.toMatchObject({ name: "user1" });
+  });
+});
diff --git a/packages/artifact-testing/fixtures/simple-model/transients.sample.ts b/packages/artifact-testing/fixtures/simple-model/transients.sample.ts
new file mode 100644
index 0000000..f2d00fd
--- /dev/null
+++ b/packages/artifact-testing/fixtures/simple-model/transients.sample.ts
@@ -0,0 +1,26 @@
+import { defineUserFactory } from "./__generated__/fabbrica";
+
+export async function correctTypeTest() {
+  const factoryWithoutTransientFields = defineUserFactory();
+  await factoryWithoutTransientFields.create();
+
+  const factoryWithTransientFields = defineUserFactory.withTransientFields({
+    a: false,
+    b: 0,
+    c: "",
+  })({
+    defaultData: async ({ seq, a, b, c }) => ({
+      name: `${seq}${a}${b}${c}`,
+    }),
+  });
+  await factoryWithTransientFields.create();
+}
+
+export async function invalidTypeTest() {
+  const UserFactory = defineUserFactory.withTransientFields({
+    // @ts-expect-error Can't use field name defined from schema as transient field name
+    id: "id",
+  })();
+
+  await UserFactory.build();
+}
diff --git a/packages/artifact-testing/fixtures/simple-model/transients.test.ts b/packages/artifact-testing/fixtures/simple-model/transients.test.ts
new file mode 100644
index 0000000..3beb71a
--- /dev/null
+++ b/packages/artifact-testing/fixtures/simple-model/transients.test.ts
@@ -0,0 +1,29 @@
+import { defineUserFactory } from "./__generated__/fabbrica";
+
+describe("Generated functions", () => {
+  describe("read transientFields from defaultData", () => {
+    const UserFactory = defineUserFactory.withTransientFields({
+      loginCount: 0,
+    })({
+      defaultData: ({ loginCount }) => ({
+        name: `user_${loginCount}`,
+      }),
+    });
+
+    test("no input data", async () => {
+      expect(UserFactory.build()).resolves.toMatchObject({ name: "user_0" });
+    });
+
+    test("with transient field", async () => {
+      expect(UserFactory.build({ loginCount: 100 })).resolves.toMatchObject({ name: "user_100" });
+    });
+
+    test("with explicit input data", async () => {
+      expect(UserFactory.build({ name: "Bob" })).resolves.toMatchObject({ name: "Bob" });
+    });
+
+    test("with both fields", async () => {
+      expect(UserFactory.build({ loginCount: 100, name: "Bob" })).resolves.toMatchObject({ name: "Bob" });
+    });
+  });
+});
diff --git a/packages/artifact-testing/package.json b/packages/artifact-testing/package.json
index 979f69e..6daffd1 100644
--- a/packages/artifact-testing/package.json
+++ b/packages/artifact-testing/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "artifact-testing",
-  "version": "2.1.5",
+  "version": "2.2.0-alpha.4",
   "scripts": {
     "clean": "rimraf -g \"fixtures/*/__generated__/client\" \"fixtures/*/dmmf.json\" built \"*.tsbuildinfo\"",
     "pretest:compile": "node scripts/generateFixtures.mjs",
diff --git a/packages/prisma-fabbrica/src/helpers/transientFields.test.ts b/packages/prisma-fabbrica/src/helpers/transientFields.test.ts
new file mode 100644
index 0000000..87d7c95
--- /dev/null
+++ b/packages/prisma-fabbrica/src/helpers/transientFields.test.ts
@@ -0,0 +1,17 @@
+import { destructure } from "./transientFields";
+
+describe(destructure, () => {
+  const defaultValues = {
+    a: 1,
+  };
+
+  test.each([
+    { inputData: undefined, expected: [{ a: 1 }, {}] },
+    { inputData: null, expected: [{ a: 1 }, {}] },
+    { inputData: {}, expected: [{ a: 1 }, {}] },
+    { inputData: { a: 2 }, expected: [{ a: 2 }, {}] },
+    { inputData: { b: 1 }, expected: [{ a: 1 }, { b: 1 }] },
+  ])("works with $inputData", ({ inputData, expected }) => {
+    expect(destructure(defaultValues, inputData)).toEqual(expected);
+  });
+});
diff --git a/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap b/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap
index 61eb449..c44fe26 100644
--- a/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap
+++ b/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap
@@ -3,12 +3,20 @@
 exports[`getSourceFile generates TypeScript AST 1`] = `
 "import type { User } from "@prisma/client";
 import type { Prisma, PrismaClient } from "@prisma/client";
-import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, } from "@quramy/prisma-fabbrica/lib/internal";
+import { createInitializer, createScreener, getScalarFieldValueGenerator, normalizeResolver, normalizeList, getSequenceCounter, createCallbackChain, destructure } from "@quramy/prisma-fabbrica/lib/internal";
 import type { ModelWithFields, Resolver, } from "@quramy/prisma-fabbrica/lib/internal";
 export { resetSequence, registerScalarFieldValueGenerator, resetScalarFieldValueGenerator } from "@quramy/prisma-fabbrica/lib/internal";
 
-type BuildDataOptions = {
+type BuildDataOptions<TTransients extends Record<string, unknown>> = {
     readonly seq: number;
+} & TTransients;
+
+type TraitName = string | symbol;
+
+type CallbackDefineOptions<TCreated, TCreateInput, TTransients extends Record<string, unknown>> = {
+    onAfterBuild?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onBeforeCreate?: (createInput: TCreateInput, transientFields: TTransients) => void | PromiseLike<void>;
+    onAfterCreate?: (created: TCreated, transientFields: TTransients) => void | PromiseLike<void>;
 };
 
 const initializer = createInitializer();
@@ -32,30 +40,36 @@ type UserFactoryDefineInput = {
     name?: string;
 };
 
-type UserFactoryDefineOptions = {
-    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions>;
+type UserTransientFields = Record<string, unknown> & Partial<Record<keyof UserFactoryDefineInput, never>>;
+
+type UserFactoryTrait<TTransients extends Record<string, unknown>> = {
+    data?: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>;
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
+
+type UserFactoryDefineOptions<TTransients extends Record<string, unknown> = Record<string, unknown>> = {
+    defaultData?: Resolver<UserFactoryDefineInput, BuildDataOptions<TTransients>>;
     traits?: {
-        [traitName: string | symbol]: {
-            data: Resolver<Partial<UserFactoryDefineInput>, BuildDataOptions>;
-        };
+        [traitName: TraitName]: UserFactoryTrait<TTransients>;
     };
-};
+} & CallbackDefineOptions<User, Prisma.UserCreateInput, TTransients>;
 
-type UserTraitKeys<TOptions extends UserFactoryDefineOptions> = keyof TOptions["traits"];
+type UserTraitKeys<TOptions extends UserFactoryDefineOptions<any>> = Exclude<keyof TOptions["traits"], number>;
 
-export interface UserFactoryInterfaceWithoutTraits {
+export interface UserFactoryInterfaceWithoutTraits<TTransients extends Record<string, unknown>> {
     readonly _factoryFor: "User";
-    build(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Prisma.UserCreateInput>;
-    buildList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    build(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildCreateInput(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput>;
+    buildList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<Prisma.UserCreateInput[]>;
+    buildList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Prisma.UserCreateInput[]>;
     pickForConnect(inputData: User): Pick<User, "id">;
-    create(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<User>;
-    createList(inputData: number | readonly Partial<Prisma.UserCreateInput>[]): PromiseLike<User[]>;
-    createForConnect(inputData?: Partial<Prisma.UserCreateInput>): PromiseLike<Pick<User, "id">>;
+    create(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User>;
+    createList(list: readonly Partial<Prisma.UserCreateInput & TTransients>[]): PromiseLike<User[]>;
+    createList(count: number, item?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<User[]>;
+    createForConnect(inputData?: Partial<Prisma.UserCreateInput & TTransients>): PromiseLike<Pick<User, "id">>;
 }
 
-export interface UserFactoryInterface<TOptions extends UserFactoryDefineOptions = UserFactoryDefineOptions> extends UserFactoryInterfaceWithoutTraits {
-    use(name: UserTraitKeys<TOptions>, ...names: readonly UserTraitKeys<TOptions>[]): UserFactoryInterfaceWithoutTraits;
+export interface UserFactoryInterface<TTransients extends Record<string, unknown> = Record<string, unknown>, TTraitName extends TraitName = TraitName> extends UserFactoryInterfaceWithoutTraits<TTransients> {
+    use(name: TTraitName, ...names: readonly TTraitName[]): UserFactoryInterfaceWithoutTraits<TTransients>;
 }
 
 function autoGenerateUserScalarsOrEnums({ seq }: {
@@ -67,38 +81,57 @@ function autoGenerateUserScalarsOrEnums({ seq }: {
     };
 }
 
-function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({ defaultData: defaultDataResolver, traits: traitsDefs = {} }: TOptions): UserFactoryInterface<TOptions> {
+function defineUserFactoryInternal<TTransients extends Record<string, unknown>, TOptions extends UserFactoryDefineOptions<TTransients>>({ defaultData: defaultDataResolver, onAfterBuild, onBeforeCreate, onAfterCreate, traits: traitsDefs = {} }: TOptions, defaultTransientFieldValues: TTransients): UserFactoryInterface<TTransients, UserTraitKeys<TOptions>> {
     const getFactoryWithTraits = (traitKeys: readonly UserTraitKeys<TOptions>[] = []) => {
         const seqKey = {};
         const getSeq = () => getSequenceCounter(seqKey);
         const screen = createScreener("User", modelFieldDefinitions);
-        const build = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const handleAfterBuild = createCallbackChain([
+            onAfterBuild,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterBuild),
+        ]);
+        const handleBeforeCreate = createCallbackChain([
+            ...traitKeys.slice().reverse().map(traitKey => traitsDefs[traitKey].onBeforeCreate),
+            onBeforeCreate,
+        ]);
+        const handleAfterCreate = createCallbackChain([
+            onAfterCreate,
+            ...traitKeys.map(traitKey => traitsDefs[traitKey].onAfterCreate),
+        ]);
+        const build = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
             const seq = getSeq();
             const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq });
-            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions>(defaultDataResolver ?? {});
+            const resolveValue = normalizeResolver<UserFactoryDefineInput, BuildDataOptions<any>>(defaultDataResolver ?? {});
+            const [transientFields, filteredInputData] = destructure(defaultTransientFieldValues, inputData);
+            const resolverInput = { seq, ...transientFields };
             const defaultData = await traitKeys.reduce(async (queue, traitKey) => {
                 const acc = await queue;
-                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions>(traitsDefs[traitKey]?.data ?? {});
-                const traitData = await resolveTraitValue({ seq });
+                const resolveTraitValue = normalizeResolver<Partial<UserFactoryDefineInput>, BuildDataOptions<TTransients>>(traitsDefs[traitKey]?.data ?? {});
+                const traitData = await resolveTraitValue(resolverInput);
                 return {
                     ...acc,
                     ...traitData,
                 };
-            }, resolveValue({ seq }));
+            }, resolveValue(resolverInput));
             const defaultAssociations = {};
-            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...inputData };
+            const data: Prisma.UserCreateInput = { ...requiredScalarData, ...defaultData, ...defaultAssociations, ...filteredInputData };
+            await handleAfterBuild(data, transientFields);
             return data;
         };
-        const buildList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => build(data)));
+        const buildList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => build(data)));
         const pickForConnect = (inputData: User) => ({
             id: inputData.id
         });
-        const create = async (inputData: Partial<Prisma.UserCreateInput> = {}) => {
+        const create = async (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => {
+            const [transientFields] = destructure(defaultTransientFieldValues, inputData);
             const data = await build(inputData).then(screen);
-            return await getClient<PrismaClient>().user.create({ data });
+            await handleBeforeCreate(data, transientFields);
+            const createdData = await getClient<PrismaClient>().user.create({ data });
+            await handleAfterCreate(createdData, transientFields);
+            return createdData;
         };
-        const createList = (inputData: number | readonly Partial<Prisma.UserCreateInput>[]) => Promise.all(normalizeList(inputData).map(data => create(data)));
-        const createForConnect = (inputData: Partial<Prisma.UserCreateInput> = {}) => create(inputData).then(pickForConnect);
+        const createList = (...args: unknown[]) => Promise.all(normalizeList<Partial<Prisma.UserCreateInput & TTransients>>(...args).map(data => create(data)));
+        const createForConnect = (inputData: Partial<Prisma.UserCreateInput & TTransients> = {}) => create(inputData).then(pickForConnect);
         return {
             _factoryFor: "User" as const,
             build,
@@ -120,14 +153,21 @@ function defineUserFactoryInternal<TOptions extends UserFactoryDefineOptions>({
     };
 }
 
+interface UserFactoryBuilder {
+    <TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<{}, UserTraitKeys<TOptions>>;
+    withTransientFields: <TTransients extends UserTransientFields>(defaultTransientFieldValues: TTransients) => <TOptions extends UserFactoryDefineOptions<TTransients>>(options?: TOptions) => UserFactoryInterface<TTransients, UserTraitKeys<TOptions>>;
+}
+
 /**
  * Define factory for {@link User} model.
  *
  * @param options
  * @returns factory {@link UserFactoryInterface}
  */
-export function defineUserFactory<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> {
-    return defineUserFactoryInternal(options ?? {});
-}
+export const defineUserFactory = (<TOptions extends UserFactoryDefineOptions>(options?: TOptions): UserFactoryInterface<TOptions> => {
+    return defineUserFactoryInternal(options ?? {}, {});
+}) as UserFactoryBuilder;
+
+defineUserFactory.withTransientFields = defaultTransientFieldValues => options => defineUserFactoryInternal(options ?? {}, defaultTransientFieldValues);
 "
 `;