Stores and Types
Store Exports
useAppStore— authentication state, current user info, menu maps, and permission tokens; persisted (isAuthenticated/custom/authTokenssurvive reload).useTabStore— the open-tabs list backing the multi-tab layout; persisted.useThemeStore— color scheme, semantic theme colors, menu layout mode, and layout toggles; persisted.
All three are created with createPersistedStore (see Store and Atom) — their state types do not need a name field; the storage key comes from the persistence options instead.
Related types:
AppStateTabTabStateColorScheme—"system" | "light" | "dark"ThemeColors—Record<SemanticColor, string>MenuLayoutMode—"vertical" | "horizontal" | "mixed"ThemeState
API and Domain Types
Entity identity:
Entity<TId = string>— base interface that only carriesid
Standalone audit field interfaces (use these for composite primary keys or non-id keyed records):
CreationTracked<TId, TDate>—createdAt/createdBy/createdByNameFullTracked<TId, TDate>— extendsCreationTrackedwithupdatedAt/updatedBy/updatedByName
Composed entity interfaces:
CreationAuditedEntity<TId, TDate>—Entity+CreationTrackedFullAuditedEntity<TId, TDate>—Entity+FullTracked
Batch parameter helper:
Many<T>— wraps alist: T[]for batch create / update payloads
User and Menu Types
Gender—"male" | "female" | "unknown"UserMenuType—"directory" | "menu" | "view" | "report", open to project-specific extension viaLiteralUnionUserMenu—type/path/name/icon?/meta?/children?UserMenuMeta—params?: Record<string, string>andsearch?: Record<string, string>bound to a menu's route, plus any keys augmented ontoRegister['menuMeta']UserInfo—detailsis typed via theRegisteraugmentation point (see below)AppCustomState— the shape ofAppState.custom; defaults toAnyObject, narrowed viaRegister['appCustomState']ChallengeSpec—{ data?: unknown; response: unknown }, the contract for one login challenge typeResolvedChallenges— the challenge-type registry resolved fromRegister['challenges'], or an openRecord<string, ChallengeSpec>when not augmentedRegister— empty interface that projects augment viadeclare moduleto refineUserInfo['details'],AppState.custom,UserMenuMeta, and the login challenge registry. For the built-inpassword_changechallenge, registerPasswordChangeChallengeSpecunderPASSWORD_CHANGE_CHALLENGE_TYPE— see Login challengesUserDetails— fallback shape (Record<string, unknown>) whenRegister['userDetails']is not augmentedOrderSpec—{ column: string; direction: "asc" | "desc" }
Extending UserInfo.details
UserInfo.details resolves through the Register interface, mirroring the pattern used by @tanstack/react-query for mutationMeta. Augment it once in your project to get strongly typed user attributes everywhere UserInfo flows through the app:
// src/types/vef-augment.d.ts
declare module "@vef-framework-react/starter" {
interface Register {
userDetails: {
department: string;
organization: string;
};
}
}
After this declaration, userInfo.details.department is typed as string across the application without forking the framework. The same Register interface also accepts appCustomState, menuMeta, and challenges members for the other extension points above.
Router Types
RouterContext
Query Helpers
extractQueryParamsnoopMutationFn