@pubflow/react 0.1.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.
Files changed (38) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +539 -0
  3. package/dist/index.d.ts +1908 -0
  4. package/dist/index.esm.js +9922 -0
  5. package/dist/index.esm.js.map +1 -0
  6. package/dist/index.js +9954 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/types/components/AdvancedFilter.d.ts +113 -0
  9. package/dist/types/components/BridgeForm/index.d.ts +6 -0
  10. package/dist/types/components/BridgeForm/styles.d.ts +62 -0
  11. package/dist/types/components/BridgeForm/types.d.ts +128 -0
  12. package/dist/types/components/BridgeForm/utils.d.ts +60 -0
  13. package/dist/types/components/BridgeList.d.ts +157 -0
  14. package/dist/types/components/BridgeTable.d.ts +110 -0
  15. package/dist/types/components/BridgeView.d.ts +39 -0
  16. package/dist/types/components/OfflineIndicator.d.ts +58 -0
  17. package/dist/types/components/auth/AccountCreationForm.d.ts +60 -0
  18. package/dist/types/components/auth/LoginForm.d.ts +76 -0
  19. package/dist/types/components/auth/PasswordResetForm.d.ts +60 -0
  20. package/dist/types/components/auth/index.d.ts +8 -0
  21. package/dist/types/components/theme/ThemeProvider.d.ts +255 -0
  22. package/dist/types/components/theme/index.d.ts +6 -0
  23. package/dist/types/context/PubflowProvider.d.ts +100 -0
  24. package/dist/types/hooks/useAuth.d.ts +32 -0
  25. package/dist/types/hooks/useBridgeApi.d.ts +14 -0
  26. package/dist/types/hooks/useBridgeApiRaw.d.ts +91 -0
  27. package/dist/types/hooks/useBridgeCrud.d.ts +193 -0
  28. package/dist/types/hooks/useBridgeMutation.d.ts +69 -0
  29. package/dist/types/hooks/useBridgeQuery.d.ts +44 -0
  30. package/dist/types/hooks/useSearchQueryBuilder.d.ts +152 -0
  31. package/dist/types/hooks/useServerAuth.d.ts +45 -0
  32. package/dist/types/index.d.ts +26 -0
  33. package/dist/types/storage/BrowserStorageAdapter.d.ts +112 -0
  34. package/dist/types/test/setup.d.ts +4 -0
  35. package/dist/types/utils/auth-utils.d.ts +37 -0
  36. package/dist/types/utils/index.d.ts +5 -0
  37. package/dist/types/utils/persistent-cache.d.ts +57 -0
  38. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,539 @@
1
+ # @pubflow/react
2
+
3
+ React adapter for the Pubflow framework with support for any React-based framework.
4
+
5
+ ## Features
6
+
7
+ - Complete React integration for Pubflow
8
+ - SWR for data fetching and caching
9
+ - Framework-agnostic design (works with any React framework)
10
+ - Support for Remix, Next.js, Create React App, and more
11
+ - Optimized for React 17+
12
+ - TypeScript support
13
+ - Customizable components
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ # Install the core package and React adapter
19
+ npm install @pubflow/core @pubflow/react
20
+
21
+ # Install SWR (required)
22
+ npm install swr
23
+
24
+ # Optional: Install Zod for schema validation
25
+ npm install zod
26
+ ```
27
+
28
+ ## Basic Usage
29
+
30
+ ### Provider Setup
31
+
32
+ Wrap your application with the `PubflowProvider`:
33
+
34
+ ```jsx
35
+ // App.jsx
36
+ import React from 'react';
37
+ import { PubflowProvider } from '@pubflow/react';
38
+
39
+ function App() {
40
+ return (
41
+ <PubflowProvider
42
+ config={{
43
+ baseUrl: 'https://api.example.com',
44
+ bridgeBasePath: '/bridge',
45
+ authBasePath: '/auth'
46
+ }}
47
+ >
48
+ <YourApp />
49
+ </PubflowProvider>
50
+ );
51
+ }
52
+
53
+ export default App;
54
+ ```
55
+
56
+ ### Authentication
57
+
58
+ Use the `useAuth` hook to access authentication functionality:
59
+
60
+ ```jsx
61
+ // Login.jsx
62
+ import React, { useState } from 'react';
63
+ import { useAuth } from '@pubflow/react';
64
+
65
+ function Login() {
66
+ const { login, isLoading } = useAuth();
67
+ const [email, setEmail] = useState('');
68
+ const [password, setPassword] = useState('');
69
+
70
+ const handleSubmit = async (e) => {
71
+ e.preventDefault();
72
+
73
+ try {
74
+ const result = await login({ email, password });
75
+
76
+ if (result.success) {
77
+ // Redirect to dashboard
78
+ }
79
+ } catch (error) {
80
+ console.error('Login failed:', error);
81
+ }
82
+ };
83
+
84
+ return (
85
+ <form onSubmit={handleSubmit}>
86
+ <input
87
+ type="email"
88
+ value={email}
89
+ onChange={(e) => setEmail(e.target.value)}
90
+ placeholder="Email"
91
+ />
92
+ <input
93
+ type="password"
94
+ value={password}
95
+ onChange={(e) => setPassword(e.target.value)}
96
+ placeholder="Password"
97
+ />
98
+ <button type="submit" disabled={isLoading}>
99
+ {isLoading ? 'Logging in...' : 'Login'}
100
+ </button>
101
+ </form>
102
+ );
103
+ }
104
+
105
+ export default Login;
106
+ ```
107
+
108
+ ### Data Fetching with SWR
109
+
110
+ Use the `useBridgeQuery` hook to fetch data:
111
+
112
+ ```jsx
113
+ // UserList.jsx
114
+ import React from 'react';
115
+ import { useBridgeApi, useBridgeQuery } from '@pubflow/react';
116
+
117
+ function UserList() {
118
+ const userService = useBridgeApi({ endpoint: 'users' });
119
+ const { data: users, isLoading, error, refetch } = useBridgeQuery(
120
+ userService,
121
+ 'list',
122
+ { limit: 10 }
123
+ );
124
+
125
+ if (isLoading) {
126
+ return <div>Loading...</div>;
127
+ }
128
+
129
+ if (error) {
130
+ return (
131
+ <div>
132
+ <div>Error: {error.message}</div>
133
+ <button onClick={refetch}>Retry</button>
134
+ </div>
135
+ );
136
+ }
137
+
138
+ return (
139
+ <div>
140
+ <h1>Users</h1>
141
+ <ul>
142
+ {users.map(user => (
143
+ <li key={user.id}>{user.name}</li>
144
+ ))}
145
+ </ul>
146
+ </div>
147
+ );
148
+ }
149
+
150
+ export default UserList;
151
+ ```
152
+
153
+ ### CRUD Operations
154
+
155
+ Use the `useBridgeCrud` hook for complete CRUD operations:
156
+
157
+ ```jsx
158
+ // UserManagement.jsx
159
+ import React, { useState } from 'react';
160
+ import { useBridgeCrud } from '@pubflow/react';
161
+
162
+ function UserManagement() {
163
+ const [formData, setFormData] = useState({ name: '', email: '' });
164
+
165
+ const {
166
+ items: users,
167
+ createItem,
168
+ updateItem,
169
+ deleteItem,
170
+ loading,
171
+ error
172
+ } = useBridgeCrud({
173
+ entityConfig: {
174
+ endpoint: 'users'
175
+ },
176
+ successMessages: {
177
+ create: 'User created successfully',
178
+ update: 'User updated successfully',
179
+ delete: 'User deleted successfully'
180
+ }
181
+ });
182
+
183
+ const handleSubmit = async (e) => {
184
+ e.preventDefault();
185
+
186
+ try {
187
+ await createItem(formData);
188
+ setFormData({ name: '', email: '' });
189
+ } catch (error) {
190
+ console.error('Failed to create user:', error);
191
+ }
192
+ };
193
+
194
+ return (
195
+ <div>
196
+ <h1>User Management</h1>
197
+
198
+ <form onSubmit={handleSubmit}>
199
+ <input
200
+ type="text"
201
+ value={formData.name}
202
+ onChange={(e) => setFormData({ ...formData, name: e.target.value })}
203
+ placeholder="Name"
204
+ />
205
+ <input
206
+ type="email"
207
+ value={formData.email}
208
+ onChange={(e) => setFormData({ ...formData, email: e.target.value })}
209
+ placeholder="Email"
210
+ />
211
+ <button type="submit" disabled={loading}>
212
+ {loading ? 'Creating...' : 'Create User'}
213
+ </button>
214
+ </form>
215
+
216
+ {error && <div>Error: {error.message}</div>}
217
+
218
+ <ul>
219
+ {users.map(user => (
220
+ <li key={user.id}>
221
+ {user.name} ({user.email})
222
+ <button onClick={() => deleteItem(user.id)}>Delete</button>
223
+ </li>
224
+ ))}
225
+ </ul>
226
+ </div>
227
+ );
228
+ }
229
+
230
+ export default UserManagement;
231
+ ```
232
+
233
+ ## Persistent Cache
234
+
235
+ Pubflow supports persistent caching to improve performance and offline experience:
236
+
237
+ ```jsx
238
+ import { PubflowProvider, createPersistentCache } from '@pubflow/react';
239
+
240
+ function App() {
241
+ // Create a persistent cache provider
242
+ const persistentCacheProvider = createPersistentCache({
243
+ prefix: 'my_app_cache',
244
+ ttl: 24 * 60 * 60 * 1000, // 24 hours
245
+ });
246
+
247
+ return (
248
+ <PubflowProvider
249
+ config={{
250
+ baseUrl: 'https://api.example.com',
251
+ bridgeBasePath: '/bridge',
252
+ authBasePath: '/auth'
253
+ }}
254
+ persistentCache={{
255
+ enabled: true,
256
+ provider: persistentCacheProvider
257
+ }}
258
+ >
259
+ <YourApp />
260
+ </PubflowProvider>
261
+ );
262
+ }
263
+ ```
264
+
265
+ For more information, see the [Persistent Cache](./docs/persistent-cache.md) documentation.
266
+
267
+ ## BridgeForm Component
268
+
269
+ Pubflow provides a powerful form component that integrates with Zod schemas and Bridge API:
270
+
271
+ ```jsx
272
+ import { BridgeForm } from '@pubflow/react';
273
+ import { z } from 'zod';
274
+
275
+ // Define schema
276
+ const userSchema = z.object({
277
+ name: z.string().min(2, 'Name must be at least 2 characters'),
278
+ email: z.string().email('Invalid email address'),
279
+ role: z.enum(['user', 'admin'], 'Role must be either user or admin')
280
+ });
281
+
282
+ function CreateUser() {
283
+ return (
284
+ <div>
285
+ <h1>Create User</h1>
286
+ <BridgeForm
287
+ schema={userSchema}
288
+ mode="create"
289
+ entityConfig={{ endpoint: 'users' }}
290
+ mainColor="#c30000"
291
+ onSuccess={(data) => {
292
+ console.log('User created:', data);
293
+ // Navigate or show success message
294
+ }}
295
+ />
296
+ </div>
297
+ );
298
+ }
299
+ ```
300
+
301
+ For more information, see the [BridgeForm documentation](./docs/bridge-form.md).
302
+
303
+ ## Schema Validation
304
+
305
+ Pubflow recommends defining schemas at the application level, not in the adapter:
306
+
307
+ ```jsx
308
+ // lib/schemas/user.js
309
+ import { z } from 'zod';
310
+
311
+ // Schema for complete user entity
312
+ export const userSchema = z.object({
313
+ id: z.string().uuid().optional(),
314
+ name: z.string().min(2, 'Name must be at least 2 characters'),
315
+ email: z.string().email('Invalid email address'),
316
+ role: z.enum(['user', 'admin'], 'Role must be either user or admin')
317
+ });
318
+
319
+ // Schema for creating a user
320
+ export const createUserSchema = userSchema.omit({
321
+ id: true
322
+ });
323
+
324
+ // Schema for updating a user
325
+ export const updateUserSchema = userSchema
326
+ .partial()
327
+ .extend({
328
+ id: z.string().uuid()
329
+ });
330
+
331
+ // TypeScript types inferred from schemas
332
+ export type User = z.infer<typeof userSchema>;
333
+ export type CreateUser = z.infer<typeof createUserSchema>;
334
+ export type UpdateUser = z.infer<typeof updateUserSchema>;
335
+ ```
336
+
337
+ These schemas can then be used with Pubflow's CRUD operations:
338
+
339
+ ```jsx
340
+ import { useBridgeCrud } from '@pubflow/react';
341
+ import { userSchema, createUserSchema, updateUserSchema } from '../lib/schemas/user';
342
+
343
+ function UsersPage() {
344
+ const {
345
+ items: users,
346
+ createItem,
347
+ updateItem,
348
+ deleteItem,
349
+ validationErrors
350
+ } = useBridgeCrud({
351
+ entityConfig: {
352
+ endpoint: 'users'
353
+ },
354
+ schemas: {
355
+ entity: userSchema,
356
+ create: createUserSchema,
357
+ update: updateUserSchema
358
+ }
359
+ });
360
+
361
+ // Component implementation...
362
+ }
363
+ ```
364
+
365
+ ## Framework Integration
366
+
367
+ Pubflow is designed to work with any React-based framework. Here are examples for popular frameworks:
368
+
369
+ For detailed Remix integration, see the [Remix Integration Guide](./docs/remix-integration.md).
370
+
371
+ ### Remix Integration
372
+
373
+ ```jsx
374
+ // app/routes/dashboard.jsx
375
+ import { useLoaderData, redirect } from '@remix-run/react';
376
+ import { json } from '@remix-run/node';
377
+ import { useRequireAuth } from '@pubflow/react';
378
+
379
+ // Server-side authentication check
380
+ export async function loader({ request }) {
381
+ // Get session from cookie
382
+ const cookieHeader = request.headers.get('Cookie');
383
+ const token = parseCookie(cookieHeader)['pubflow_session_token'];
384
+
385
+ if (!token) {
386
+ return redirect('/login');
387
+ }
388
+
389
+ // You can also fetch initial data here
390
+ return json({ initialData: 'some data' });
391
+ }
392
+
393
+ // Client-side component
394
+ export default function Dashboard() {
395
+ const { initialData } = useLoaderData();
396
+
397
+ // Client-side authentication check
398
+ useRequireAuth({
399
+ allowedTypes: ['admin', 'user'],
400
+ redirectTo: '/login',
401
+ // Use Remix's navigate function
402
+ redirectFn: (path) => {
403
+ window.location.href = path;
404
+ }
405
+ });
406
+
407
+ return (
408
+ <div>
409
+ <h1>Dashboard</h1>
410
+ {/* Dashboard content */}
411
+ </div>
412
+ );
413
+ }
414
+ ```
415
+
416
+ ### Next.js Integration
417
+
418
+ ```jsx
419
+ // pages/dashboard.jsx
420
+ import { useRouter } from 'next/router';
421
+ import { useRequireAuth } from '@pubflow/react';
422
+
423
+ export default function Dashboard() {
424
+ const router = useRouter();
425
+
426
+ // Client-side authentication check
427
+ useRequireAuth({
428
+ allowedTypes: ['admin', 'user'],
429
+ redirectTo: '/login',
430
+ // Use Next.js router
431
+ redirectFn: (path) => {
432
+ router.push(path);
433
+ }
434
+ });
435
+
436
+ return (
437
+ <div>
438
+ <h1>Dashboard</h1>
439
+ {/* Dashboard content */}
440
+ </div>
441
+ );
442
+ }
443
+ ```
444
+
445
+ ### Create React App Integration
446
+
447
+ ```jsx
448
+ // src/pages/Dashboard.jsx
449
+ import { useNavigate } from 'react-router-dom';
450
+ import { useRequireAuth } from '@pubflow/react';
451
+
452
+ export default function Dashboard() {
453
+ const navigate = useNavigate();
454
+
455
+ // Client-side authentication check
456
+ useRequireAuth({
457
+ allowedTypes: ['admin', 'user'],
458
+ redirectTo: '/login',
459
+ // Use React Router's navigate function
460
+ redirectFn: (path) => {
461
+ navigate(path);
462
+ }
463
+ });
464
+
465
+ return (
466
+ <div>
467
+ <h1>Dashboard</h1>
468
+ {/* Dashboard content */}
469
+ </div>
470
+ );
471
+ }
472
+ ```
473
+
474
+ ## Components
475
+
476
+ ### BridgeView
477
+
478
+ The `BridgeView` component conditionally renders content based on authentication and user type:
479
+
480
+ ```jsx
481
+ import { BridgeView } from '@pubflow/react';
482
+
483
+ // Basic example
484
+ <BridgeView>
485
+ <div>This content is only visible to authenticated users</div>
486
+ </BridgeView>
487
+
488
+ // Only for admins
489
+ <BridgeView
490
+ allowedTypes="admin"
491
+ fallback={<div>You don't have permission to view this content</div>}
492
+ >
493
+ <div>This content is only visible to admins</div>
494
+ </BridgeView>
495
+
496
+ // Multiple user types
497
+ <BridgeView
498
+ allowedTypes={['admin', 'editor']}
499
+ loadingComponent={<div>Loading...</div>}
500
+ onUnauthorized={() => console.log('User not authorized')}
501
+ >
502
+ <div>This content is visible to admins and editors</div>
503
+ </BridgeView>
504
+ ```
505
+
506
+ ### BridgeTable
507
+
508
+ The `BridgeTable` component displays data in a table with sorting, filtering, and pagination:
509
+
510
+ ```jsx
511
+ import { BridgeTable } from '@pubflow/react';
512
+
513
+ <BridgeTable
514
+ columns={[
515
+ { key: 'name', header: 'Name', sortable: true },
516
+ { key: 'email', header: 'Email', sortable: true },
517
+ { key: 'role', header: 'Role', sortable: true },
518
+ {
519
+ key: 'createdAt',
520
+ header: 'Created At',
521
+ cell: (item) => new Date(item.createdAt).toLocaleDateString(),
522
+ sortable: true
523
+ }
524
+ ]}
525
+ entityConfig={{
526
+ endpoint: 'users'
527
+ }}
528
+ showSearch={true}
529
+ showPagination={true}
530
+ onRowClick={(user) => console.log('Selected user:', user)}
531
+ actions={(user) => (
532
+ <button onClick={() => handleDelete(user.id)}>Delete</button>
533
+ )}
534
+ />
535
+ ```
536
+
537
+ ## License
538
+
539
+ AGPL-3.0-or-later