@iblai/data-layer
v1.1.2
Published
ibl.ai data layer
Readme
@iblai/data-layer
A Redux Toolkit-based data layer package for IBL AI applications, providing centralized state management and API integrations using RTK Query.
Installation
pnpm add @iblai/data-layerOverview
The data-layer package provides:
- RTK Query API slices for all IBL AI API endpoints
- Redux store configuration with pre-configured slices
- Type-safe API hooks for React components
- Centralized state management for auth, chat, subscriptions, and more
Getting Started
1. Setup Redux Store
Wrap your application with the Redux Provider:
import { Provider } from 'react-redux';
import { store } from '@iblai/data-layer';
function App() {
return (
<Provider store={store}>
<YourApp />
</Provider>
);
}2. Using API Hooks
The package provides auto-generated hooks for all API endpoints:
import { useGetUserProfileQuery, useUpdateUserProfileMutation } from '@iblai/data-layer';
function UserProfile() {
// Query hook - automatically fetches data
const { data: profile, isLoading, error } = useGetUserProfileQuery();
// Mutation hook - for updates
const [updateProfile, { isLoading: isUpdating }] = useUpdateUserProfileMutation();
const handleSave = async (data) => {
await updateProfile(data).unwrap();
};
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{profile.name}</h1>
{/* Your profile UI */}
</div>
);
}Available API Slices
Core APIs
import {
// User & Auth
useGetUserProfileQuery,
useUpdateUserProfileMutation,
useLoginMutation,
// Tenants
useGetTenantsQuery,
useGetTenantQuery,
useCreateTenantMutation,
// Platform
useGetPlatformConfigQuery,
} from '@iblai/data-layer';AI & Chat APIs
import {
// Mentors
useGetMentorsQuery,
useGetMentorQuery,
useCreateMentorMutation,
// Chat Sessions
useGetChatSessionsQuery,
useCreateChatSessionMutation,
// Memory
useGetMemoriesQuery,
useCreateMemoryMutation,
} from '@iblai/data-layer';Subscription APIs
import {
// Stripe Integration
useGetSubscriptionQuery,
useCreateCheckoutSessionMutation,
useCreateCustomerPortalSessionMutation,
// Pricing
useGetPricingPlansQuery,
} from '@iblai/data-layer';Features
Automatic Caching
RTK Query automatically caches API responses and handles cache invalidation:
// This query result is cached
const { data } = useGetUserProfileQuery();
// Subsequent calls use cached data
const { data: sameData } = useGetUserProfileQuery(); // No network requestOptimistic Updates
const [updateProfile] = useUpdateUserProfileMutation();
const handleUpdate = async (newData) => {
try {
await updateProfile({
id: userId,
...newData,
}).unwrap();
// UI updates optimistically before API response
} catch (error) {
// Error handling
}
};Manual Cache Invalidation
import { useDispatch } from 'react-redux';
import { apiSlice } from '@iblai/data-layer';
function RefreshButton() {
const dispatch = useDispatch();
const handleRefresh = () => {
// Invalidate specific tags
dispatch(apiSlice.util.invalidateTags(['User']));
// Or reset entire API state
dispatch(apiSlice.util.resetApiState());
};
return <button onClick={handleRefresh}>Refresh</button>;
}Polling
// Poll every 5 seconds
const { data } = useGetChatSessionsQuery(undefined, {
pollingInterval: 5000,
});Conditional Fetching
// Only fetch when userId is available
const { data } = useGetUserProfileQuery(userId, {
skip: !userId,
});Store Structure
The store includes the following slices:
{
api: RTKQueryState, // All API data
auth: AuthState, // Authentication state
chat: ChatState, // Chat sessions and messages
files: FilesState, // File uploads and attachments
subscription: SubscriptionState, // Subscription info
}Accessing Store State
import { useSelector } from 'react-redux';
import { selectIsLoggedIn, selectCurrentUser } from '@iblai/data-layer';
function Header() {
const isLoggedIn = useSelector(selectIsLoggedIn);
const user = useSelector(selectCurrentUser);
return (
<header>
{isLoggedIn ? `Welcome ${user.name}` : 'Please log in'}
</header>
);
}TypeScript Support
All APIs are fully typed:
import type { UserProfile, Tenant, Mentor } from '@iblai/data-layer';
const { data } = useGetUserProfileQuery();
// data is typed as UserProfile | undefined
const { data: tenant } = useGetTenantQuery(tenantId);
// tenant is typed as Tenant | undefinedError Handling
const { data, error, isError } = useGetUserProfileQuery();
if (isError) {
if ('status' in error) {
// RTK Query error
const errMsg = 'error' in error ? error.error : JSON.stringify(error.data);
return <div>Error: {errMsg}</div>;
} else {
// Serialized error
return <div>Error: {error.message}</div>;
}
}Advanced Usage
Custom Endpoints
Extend the API slice with custom endpoints:
import { apiSlice } from '@iblai/data-layer';
const extendedApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
getCustomData: builder.query({
query: () => '/custom-endpoint',
}),
}),
});
export const { useGetCustomDataQuery } = extendedApi;Prefetching
import { useDispatch } from 'react-redux';
import { apiSlice } from '@iblai/data-layer';
function PrefetchExample() {
const dispatch = useDispatch();
const prefetchUserProfile = () => {
dispatch(
apiSlice.util.prefetch('getUserProfile', userId, { force: true })
);
};
return <button onMouseEnter={prefetchUserProfile}>Hover to prefetch</button>;
}Contributing
We welcome contributions! Please read our contributing guidelines.
Development
Local Development Setup
When developing locally, use a local registry to publish packages:
make publish-localConfigure your .npmrc:
//localhost:4873/:_authToken=<token>
@iblai:registry=http://localhost:4873/Building
pnpm buildTesting
pnpm testLicense
ISC
