User Manager
The flagship export: the User base class. Subclass it, attach a cache driver, call boot().
Minimum subclass
import { User as BaseUser, UserCacheDriverInterface } from "@mongez/user";
class AppUser extends BaseUser { protected cacheDriver: UserCacheDriverInterface = myDriver;}
const user = new AppUser();user.boot();The cacheDriver field is the only thing you usually need. Everything else has a default.
Protected fields
| Field | Type | Default | Purpose |
|---|---|---|---|
cacheDriver | UserCacheDriverInterface | undefined | undefined | Where userData is persisted between sessions. If omitted, no persistence — session-only. |
permissions | object | {} | The permissions object queried by can(). Set via setPermissions(). |
userData | object | {} | The current user payload. Set internally by boot / login / update / set. |
accessTokenKey | string | "accessToken" | Which key inside userData holds the bearer token. |
cacheKey | string | "user" | The cache-driver key that stores the whole payload. |
enableEvents | boolean | false | Whether to instantiate UserEventsListener on this.events. |
eventsBaseName | string | undefined | cacheKey | Namespace for the event bus topic. |
boot()
Always required. The constructor does NOT touch the cache driver.
public boot(): UserInterface { this.userData = this.cacheDriver?.get(this.getCacheKey()) || {};
if (this.enableEvents) { this.events = new UserEventsListener(this.eventsBaseName || this.cacheKey); this.events.triggerBoot(this.userData, this); }
return this;}So:
- Read the cache → hydrate
userData(or{}if absent). - If
enableEventsis true, instantiate the listener onthis.eventsand fireboot. - Return
thisso you can chain (new AppUser().boot()).
Identity methods
user.isLoggedIn(); // boolean — getAccessToken().length > 0user.isNotLoggedIn(); // !isLoggedIn()user.id; // shorthand: this.get("id")user.getCacheKey(); // returns the configured cacheKeyuser.getAccessTokenKey(); // returns the configured accessTokenKeyuser.setAccessTokenKey(s); // change it at runtime; returns `this`Session methods
login(userData)
user.login({ id: 1, name: "Ada", email: "ada@example.com", accessToken: "eyJhbGc…",});Order of operations:
- Fire
loginevent (BEFORE the data is committed — listeners seethis.userDatastill as the previous value). - Call
update(userData)internally, which:- Preserves the previous token if not in the new payload.
- Replaces
this.userDatawithuserData. - Fires
keyChangefor every key. - Writes to the cache driver.
- Fires
change.
Returns this.
logout()
user.logout();- Clears
this.userDatato{}. - Removes the entry from the cache driver.
- Fires
logout.
update(userData)
user.update({ id: 1, name: "Grace", email: "grace@example.com" });Replaces the whole payload. If userData does not include the access token, the previous token is preserved. Fires per-key keyChange events and then change.
Read / write methods
Dot-notation supported via @mongez/reinforcements.
user.get("name"); // "Ada"user.get("profile.address.country"); // "Egypt"user.get("missing", "fallback"); // "fallback"user.set("profile.country", "Egypt"); // creates nested object if neededuser.all(); // entire userDataset is a no-op when the new value is referentially equal to the current value at that key — user.set("name", user.get("name")) doesn’t fire keyChange.
Token shortcuts
user.getAccessToken(); // string — "" when not logged inuser.setAccessToken("new"); // user.set(accessTokenKey, "new")user.refreshToken("new"); // alias for setAccessTokenPermissions
See permissions.md for the full pattern.
user.setPermissions({ posts: { create: true } });user.can("posts.create"); // trueuser.can("posts.delete"); // false (truthy check, missing → falsy)Examples
Bearer token with a non-default key
class AppUser extends BaseUser { protected cacheDriver = myDriver; protected accessTokenKey = "jwt"; // your API returns { jwt: "…" }}
user.login({ id: 1, jwt: "eyJ…" });user.isLoggedIn(); // trueuser.getAccessToken(); // "eyJ…"A typed user with implements UserInterface
import { User as BaseUser, UserInterface, UserCacheDriverInterface } from "@mongez/user";
class AppUser extends BaseUser implements UserInterface { protected cacheDriver: UserCacheDriverInterface = myDriver;}This catches any future drift between the base class’s method signatures and what your subclass exposes.
Chain new and boot()
const user = new AppUser().boot() as AppUser;boot() returns UserInterface, so cast back to the concrete type if you want subclass-specific methods.