Extend the User Object
Learn how to add custom fields and metadata to the user profile using JopiJS's interface merging system.
Overview
Every application has unique requirements for user data. While JopiJS provides a standard set of fields (id, email, roles), you will likely need to add custom metadata like a birth date, phone number, or preferences.
In JopiJS, this is achieved through Interface Merging. Because the user object is shared via a virtual path, any module can contribute new fields to the global IUserInfos type without breaking existing code.
1. The Core Interface
The standard user object is defined by a base interface shared at the path @/lib/jopijs.auth.IUserInfos. By default, JopiJS provides the following structure:
interface IUserInfos {
id: string;
roles?: string[];
email?: string;
fullName?: string;
nickName?: string;
firstName?: string;
lastName?: string;
avatarUrl?: string;
[key: string]: any; // Allows for dynamic extensibility
}Field Descriptions
| Field | Type | Optional? | Description |
|---|---|---|---|
id | string | No | The unique identifier for the user. |
roles | string[] | Yes | A list of roles assigned to the user (e.g., ["admin"]). |
email | string | Yes | The user's email address. |
fullName | string | Yes | The complete name (e.g., "John Doe"). |
nickName | string | Yes | A shorter public name or handle. |
firstName | string | Yes | The user's first name. |
lastName | string | Yes | The user's family name. |
avatarUrl | string | Yes | URL to the user's profile picture. |
[key: string] | any | Yes | Catch-all for any other custom metadata. |
2. Adding Custom Fields
To add fields, you must create a new module that "merges" its own definition into the core interface.
Step A: Folder Structure
Create the following structure in your custom module. The interface.merge file is the key marker here.
src/ mod_custom_profile/
└── @alias/lib/jopijs.auth.IUserInfos/
├── index.ts
├── interface.merge # <--- Tells JopiJS to MERGE definitions
└── high.priority # Recommended to ensure availabilityStep B: The Definition
In your index.ts, update the IUserInfos interface with your new fields. JopiJS will automatically combine this with the original version.
export default interface IUserInfos {
phoneNumber?: string;
birthDate_year?: number;
birthDate_month?: number;
birthDate_day?: number;
preferences?: {
darkMode: boolean;
newsletter: boolean;
};
}3. Populating the Data
Once the type is extended, you need to ensure your data source (JSON file or Database) actually provides these fields.
If using JSON (Default)
Override the shared user list with your own version containing the new fields.
├── index.ts
├── high.priority # Force JopiJS to use THIS list
└── user.gen.json[
{
"authInfos": { "login": "admin", "password": "admin" },
"userInfos": {
"id": "admin",
"roles": ["admin", "bigboss"],
"fullName": "The Admin",
"phoneNumber": "+33 6 00 00 00 00",
"birthDate_year": 1990
}
}
]If using a Database
Simply update your findUser override to return the new fields from your database query.
See the Backend Logic section in the Authentication guide for more details.
4. Using the Data in UI
To access these fields in your React components, use the useGetInfos hook. Thanks to TypeScript and JopiJS's merging, you will get full auto-completion for your custom fields!
import useGetInfos from "@/hooks/jopijs.user.useGetInfos";
export default function UserProfile() {
const user = useGetInfos();
if (!user) return null;
return (
<div>
<h1>Hello, {user.fullName}</h1>
<p>Birth Year: {user.birthDate_year}</p>
<p>Phone: {user.phoneNumber}</p>
</div>
);
}Internal Shortcut: The hook @/hooks/jopijs.user.useGetInfos is provided by the @jopijs/jopimod_uicore module, which is a core dependency of the authentication system.
Summary
- Define: Create a folder
@alias/lib/jopijs.auth.IUserInfos/in your module. - Marker: Add an empty
interface.mergefile. - Code: Export a default interface with your new fields.
- Data: Update your user provider (JSON or DB) to include the values.
- Enjoy: Use the data anywhere with full TypeScript support.