ibl.ai data layer
npm install @iblai/data-layerA Redux Toolkit-based data layer package for IBL AI applications, providing centralized state management and API integrations using RTK Query.
``bash`
pnpm add @iblai/data-layer
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
Wrap your application with the Redux Provider:
`tsx
import { Provider } from 'react-redux';
import { store } from '@iblai/data-layer';
function App() {
return (
);
}
`
The package provides auto-generated hooks for all API endpoints:
`tsx
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
return (
Available API Slices
$3
`tsx
import {
// User & Auth
useGetUserProfileQuery,
useUpdateUserProfileMutation,
useLoginMutation, // Tenants
useGetTenantsQuery,
useGetTenantQuery,
useCreateTenantMutation,
// Platform
useGetPlatformConfigQuery,
} from '@iblai/data-layer';
`$3
`tsx
import {
// Mentors
useGetMentorsQuery,
useGetMentorQuery,
useCreateMentorMutation, // Chat Sessions
useGetChatSessionsQuery,
useCreateChatSessionMutation,
// Memory
useGetMemoriesQuery,
useCreateMemoryMutation,
} from '@iblai/data-layer';
`$3
`tsx
import {
// Stripe Integration
useGetSubscriptionQuery,
useCreateCheckoutSessionMutation,
useCreateCustomerPortalSessionMutation, // Pricing
useGetPricingPlansQuery,
} from '@iblai/data-layer';
`Features
$3
RTK Query automatically caches API responses and handles cache invalidation:
`tsx
// This query result is cached
const { data } = useGetUserProfileQuery();// Subsequent calls use cached data
const { data: sameData } = useGetUserProfileQuery(); // No network request
`$3
`tsx
const [updateProfile] = useUpdateUserProfileMutation();const handleUpdate = async (newData) => {
try {
await updateProfile({
id: userId,
...newData,
}).unwrap();
// UI updates optimistically before API response
} catch (error) {
// Error handling
}
};
`$3
`tsx
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 ;
}
`$3
`tsx
// Poll every 5 seconds
const { data } = useGetChatSessionsQuery(undefined, {
pollingInterval: 5000,
});
`$3
`tsx
// Only fetch when userId is available
const { data } = useGetUserProfileQuery(userId, {
skip: !userId,
});
`Store Structure
The store includes the following slices:
`typescript
{
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
}
`$3
`tsx
import { useSelector } from 'react-redux';
import { selectIsLoggedIn, selectCurrentUser } from '@iblai/data-layer';function Header() {
const isLoggedIn = useSelector(selectIsLoggedIn);
const user = useSelector(selectCurrentUser);
return (
{isLoggedIn ?
Welcome ${user.name} : 'Please log in'}
);
}
`TypeScript Support
All APIs are fully typed:
`tsx
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 | undefined
`Error Handling
`tsx
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
Error: {errMsg};
} else {
// Serialized error
return Error: {error.message};
}
}
`Advanced Usage
$3
Extend the API slice with custom endpoints:
`tsx
import { apiSlice } from '@iblai/data-layer';const extendedApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
getCustomData: builder.query({
query: () => '/custom-endpoint',
}),
}),
});
export const { useGetCustomDataQuery } = extendedApi;
`$3
`tsx
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 ;
}
`Contributing
We welcome contributions! Please read our contributing guidelines.
Development
$3
When developing locally, use a local registry to publish packages:
`bash
make publish-local
`Configure your
.npmrc:`bash
//localhost:4873/:_authToken=
@iblai:registry=http://localhost:4873/
`$3
`bash
pnpm build
`$3
`bash
pnpm test
``ISC