@iblai/data-layer 0.3.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,24 +1,330 @@
1
- # ibl web mobile data layer
1
+ # @iblai/data-layer
2
+
3
+ A Redux Toolkit-based data layer package for IBL AI applications, providing centralized state management and API integrations using RTK Query.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @iblai/data-layer
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ The data-layer package provides:
14
+ - **RTK Query API slices** for all IBL AI API endpoints
15
+ - **Redux store configuration** with pre-configured slices
16
+ - **Type-safe API hooks** for React components
17
+ - **Centralized state management** for auth, chat, subscriptions, and more
18
+
19
+ ## Getting Started
20
+
21
+ ### 1. Setup Redux Store
22
+
23
+ Wrap your application with the Redux Provider:
24
+
25
+ ```tsx
26
+ import { Provider } from 'react-redux';
27
+ import { store } from '@iblai/data-layer';
28
+
29
+ function App() {
30
+ return (
31
+ <Provider store={store}>
32
+ <YourApp />
33
+ </Provider>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ### 2. Using API Hooks
39
+
40
+ The package provides auto-generated hooks for all API endpoints:
41
+
42
+ ```tsx
43
+ import { useGetUserProfileQuery, useUpdateUserProfileMutation } from '@iblai/data-layer';
44
+
45
+ function UserProfile() {
46
+ // Query hook - automatically fetches data
47
+ const { data: profile, isLoading, error } = useGetUserProfileQuery();
48
+
49
+ // Mutation hook - for updates
50
+ const [updateProfile, { isLoading: isUpdating }] = useUpdateUserProfileMutation();
51
+
52
+ const handleSave = async (data) => {
53
+ await updateProfile(data).unwrap();
54
+ };
55
+
56
+ if (isLoading) return <div>Loading...</div>;
57
+ if (error) return <div>Error: {error.message}</div>;
58
+
59
+ return (
60
+ <div>
61
+ <h1>{profile.name}</h1>
62
+ {/* Your profile UI */}
63
+ </div>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ## Available API Slices
69
+
70
+ ### Core APIs
71
+
72
+ ```tsx
73
+ import {
74
+ // User & Auth
75
+ useGetUserProfileQuery,
76
+ useUpdateUserProfileMutation,
77
+ useLoginMutation,
78
+
79
+ // Tenants
80
+ useGetTenantsQuery,
81
+ useGetTenantQuery,
82
+ useCreateTenantMutation,
83
+
84
+ // Platform
85
+ useGetPlatformConfigQuery,
86
+ } from '@iblai/data-layer';
87
+ ```
88
+
89
+ ### AI & Chat APIs
90
+
91
+ ```tsx
92
+ import {
93
+ // Mentors
94
+ useGetMentorsQuery,
95
+ useGetMentorQuery,
96
+ useCreateMentorMutation,
97
+
98
+ // Chat Sessions
99
+ useGetChatSessionsQuery,
100
+ useCreateChatSessionMutation,
101
+
102
+ // Memory
103
+ useGetMemoriesQuery,
104
+ useCreateMemoryMutation,
105
+ } from '@iblai/data-layer';
106
+ ```
107
+
108
+ ### Subscription APIs
109
+
110
+ ```tsx
111
+ import {
112
+ // Stripe Integration
113
+ useGetSubscriptionQuery,
114
+ useCreateCheckoutSessionMutation,
115
+ useCreateCustomerPortalSessionMutation,
116
+
117
+ // Pricing
118
+ useGetPricingPlansQuery,
119
+ } from '@iblai/data-layer';
120
+ ```
121
+
122
+ ## Features
123
+
124
+ ### Automatic Caching
125
+
126
+ RTK Query automatically caches API responses and handles cache invalidation:
127
+
128
+ ```tsx
129
+ // This query result is cached
130
+ const { data } = useGetUserProfileQuery();
131
+
132
+ // Subsequent calls use cached data
133
+ const { data: sameData } = useGetUserProfileQuery(); // No network request
134
+ ```
135
+
136
+ ### Optimistic Updates
137
+
138
+ ```tsx
139
+ const [updateProfile] = useUpdateUserProfileMutation();
140
+
141
+ const handleUpdate = async (newData) => {
142
+ try {
143
+ await updateProfile({
144
+ id: userId,
145
+ ...newData,
146
+ }).unwrap();
147
+ // UI updates optimistically before API response
148
+ } catch (error) {
149
+ // Error handling
150
+ }
151
+ };
152
+ ```
153
+
154
+ ### Manual Cache Invalidation
155
+
156
+ ```tsx
157
+ import { useDispatch } from 'react-redux';
158
+ import { apiSlice } from '@iblai/data-layer';
159
+
160
+ function RefreshButton() {
161
+ const dispatch = useDispatch();
162
+
163
+ const handleRefresh = () => {
164
+ // Invalidate specific tags
165
+ dispatch(apiSlice.util.invalidateTags(['User']));
166
+
167
+ // Or reset entire API state
168
+ dispatch(apiSlice.util.resetApiState());
169
+ };
170
+
171
+ return <button onClick={handleRefresh}>Refresh</button>;
172
+ }
173
+ ```
174
+
175
+ ### Polling
176
+
177
+ ```tsx
178
+ // Poll every 5 seconds
179
+ const { data } = useGetChatSessionsQuery(undefined, {
180
+ pollingInterval: 5000,
181
+ });
182
+ ```
183
+
184
+ ### Conditional Fetching
185
+
186
+ ```tsx
187
+ // Only fetch when userId is available
188
+ const { data } = useGetUserProfileQuery(userId, {
189
+ skip: !userId,
190
+ });
191
+ ```
192
+
193
+ ## Store Structure
194
+
195
+ The store includes the following slices:
196
+
197
+ ```typescript
198
+ {
199
+ api: RTKQueryState, // All API data
200
+ auth: AuthState, // Authentication state
201
+ chat: ChatState, // Chat sessions and messages
202
+ files: FilesState, // File uploads and attachments
203
+ subscription: SubscriptionState, // Subscription info
204
+ }
205
+ ```
206
+
207
+ ### Accessing Store State
208
+
209
+ ```tsx
210
+ import { useSelector } from 'react-redux';
211
+ import { selectIsLoggedIn, selectCurrentUser } from '@iblai/data-layer';
212
+
213
+ function Header() {
214
+ const isLoggedIn = useSelector(selectIsLoggedIn);
215
+ const user = useSelector(selectCurrentUser);
216
+
217
+ return (
218
+ <header>
219
+ {isLoggedIn ? `Welcome ${user.name}` : 'Please log in'}
220
+ </header>
221
+ );
222
+ }
223
+ ```
224
+
225
+ ## TypeScript Support
226
+
227
+ All APIs are fully typed:
228
+
229
+ ```tsx
230
+ import type { UserProfile, Tenant, Mentor } from '@iblai/data-layer';
231
+
232
+ const { data } = useGetUserProfileQuery();
233
+ // data is typed as UserProfile | undefined
234
+
235
+ const { data: tenant } = useGetTenantQuery(tenantId);
236
+ // tenant is typed as Tenant | undefined
237
+ ```
238
+
239
+ ## Error Handling
240
+
241
+ ```tsx
242
+ const { data, error, isError } = useGetUserProfileQuery();
243
+
244
+ if (isError) {
245
+ if ('status' in error) {
246
+ // RTK Query error
247
+ const errMsg = 'error' in error ? error.error : JSON.stringify(error.data);
248
+ return <div>Error: {errMsg}</div>;
249
+ } else {
250
+ // Serialized error
251
+ return <div>Error: {error.message}</div>;
252
+ }
253
+ }
254
+ ```
255
+
256
+ ## Advanced Usage
257
+
258
+ ### Custom Endpoints
259
+
260
+ Extend the API slice with custom endpoints:
261
+
262
+ ```tsx
263
+ import { apiSlice } from '@iblai/data-layer';
264
+
265
+ const extendedApi = apiSlice.injectEndpoints({
266
+ endpoints: (builder) => ({
267
+ getCustomData: builder.query({
268
+ query: () => '/custom-endpoint',
269
+ }),
270
+ }),
271
+ });
272
+
273
+ export const { useGetCustomDataQuery } = extendedApi;
274
+ ```
275
+
276
+ ### Prefetching
277
+
278
+ ```tsx
279
+ import { useDispatch } from 'react-redux';
280
+ import { apiSlice } from '@iblai/data-layer';
281
+
282
+ function PrefetchExample() {
283
+ const dispatch = useDispatch();
284
+
285
+ const prefetchUserProfile = () => {
286
+ dispatch(
287
+ apiSlice.util.prefetch('getUserProfile', userId, { force: true })
288
+ );
289
+ };
290
+
291
+ return <button onMouseEnter={prefetchUserProfile}>Hover to prefetch</button>;
292
+ }
293
+ ```
2
294
 
3
295
  ## Contributing
4
296
 
5
297
  We welcome contributions! Please read our [contributing guidelines](CONTRIBUTING.md).
6
298
 
7
- ## Dev setup
299
+ ## Development
8
300
 
9
- When developing locally, you should use a local registry to publish the packages and iterate fast.
301
+ ### Local Development Setup
10
302
 
11
- Run the following command to publish locally:
303
+ When developing locally, use a local registry to publish packages:
12
304
 
13
305
  ```bash
14
306
  make publish-local
15
307
  ```
16
308
 
17
- By default, we use verdaccio as the local registry.
18
-
19
- Don't forge to setup the `.npmrc` file to use the local registry.
309
+ Configure your `.npmrc`:
20
310
 
21
311
  ```bash
22
312
  //localhost:4873/:_authToken=<token>
23
313
  @iblai:registry=http://localhost:4873/
24
314
  ```
315
+
316
+ ### Building
317
+
318
+ ```bash
319
+ pnpm build
320
+ ```
321
+
322
+ ### Testing
323
+
324
+ ```bash
325
+ pnpm test
326
+ ```
327
+
328
+ ## License
329
+
330
+ ISC