@jmruthers/pace-core 0.5.39 → 0.5.41
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/dist/rbac/cli/policy-manager.js +278 -0
- package/dist/rbac/cli/policy-manager.js.map +1 -0
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +2 -2
- package/docs/implementation-guides/data-tables.md +189 -0
- package/docs/rbac/README-rbac-rls-integration.md +358 -0
- package/docs/rbac/examples/rbac-rls-integration-example.md +332 -0
- package/docs/rbac/rbac-rls-integration.md +377 -0
- package/package.json +19 -3
- package/src/rbac/cli/policy-manager.ts +443 -0
package/docs/api/modules.md
CHANGED
|
@@ -155,6 +155,9 @@ The DataTable component has a comprehensive prop interface. Here are the key pro
|
|
|
155
155
|
- `columnOrder?: string[]` - **Column ordering** - Array of column IDs in desired order
|
|
156
156
|
|
|
157
157
|
### Event Handlers
|
|
158
|
+
|
|
159
|
+
⚠️ **Critical**: DataTable is a controlled component. You must update your local state after CRUD operations to keep the UI in sync.
|
|
160
|
+
|
|
158
161
|
- `onEditRow?: (row: TData, data: Partial<TData>) => void` - Row edit handler
|
|
159
162
|
- `onDeleteRow?: (row: TData) => void` - Row deletion handler (also used as fallback for bulk delete)
|
|
160
163
|
- `onCreateRow?: (data: Partial<TData>) => void` - Row creation handler
|
|
@@ -175,6 +178,184 @@ The DataTable component has a comprehensive prop interface. Here are the key pro
|
|
|
175
178
|
### Row Actions
|
|
176
179
|
- `actions?: any[]` - Custom row actions for each row
|
|
177
180
|
|
|
181
|
+
## CRUD Operations Implementation
|
|
182
|
+
|
|
183
|
+
### Understanding Controlled Components
|
|
184
|
+
|
|
185
|
+
The DataTable is a **controlled component** that displays whatever data you pass to it. When implementing CRUD operations, you must manage both the database operations AND the local state updates to keep the UI in sync.
|
|
186
|
+
|
|
187
|
+
**Two-step process for all CRUD operations:**
|
|
188
|
+
1. **Perform the database operation** (create, update, delete)
|
|
189
|
+
2. **Update your local state** to reflect the changes
|
|
190
|
+
|
|
191
|
+
### Complete CRUD Examples
|
|
192
|
+
|
|
193
|
+
#### State Management Setup
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { useState, useEffect } from 'react';
|
|
197
|
+
import { DataTable } from '@jmruthers/pace-core';
|
|
198
|
+
|
|
199
|
+
function MealsPage() {
|
|
200
|
+
const [meals, setMeals] = useState<Meal[]>([]);
|
|
201
|
+
const [loading, setLoading] = useState(true);
|
|
202
|
+
|
|
203
|
+
// Load initial data
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
loadMeals().then(setMeals).finally(() => setLoading(false));
|
|
206
|
+
}, []);
|
|
207
|
+
|
|
208
|
+
// ... rest of component
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### Create Operation
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const handleCreateRow = async (data: Partial<Meal>) => {
|
|
216
|
+
try {
|
|
217
|
+
// 1. Create in database
|
|
218
|
+
const newMeal = await supabase
|
|
219
|
+
.from('meals')
|
|
220
|
+
.insert(data)
|
|
221
|
+
.select()
|
|
222
|
+
.single();
|
|
223
|
+
|
|
224
|
+
if (newMeal.error) throw newMeal.error;
|
|
225
|
+
|
|
226
|
+
// 2. Update local state - ADD the new row
|
|
227
|
+
setMeals(prevMeals => [...prevMeals, newMeal.data]);
|
|
228
|
+
|
|
229
|
+
console.log('Meal created successfully');
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error('Failed to create meal:', error);
|
|
232
|
+
// Show error message to user
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Update Operation
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
const handleEditRow = async (row: Meal, data: Partial<Meal>) => {
|
|
241
|
+
try {
|
|
242
|
+
// 1. Update in database
|
|
243
|
+
const { error } = await supabase
|
|
244
|
+
.from('meals')
|
|
245
|
+
.update(data)
|
|
246
|
+
.eq('meal_id', row.meal_id);
|
|
247
|
+
|
|
248
|
+
if (error) throw error;
|
|
249
|
+
|
|
250
|
+
// 2. Update local state - REPLACE the updated row
|
|
251
|
+
setMeals(prevMeals =>
|
|
252
|
+
prevMeals.map(meal =>
|
|
253
|
+
meal.meal_id === row.meal_id
|
|
254
|
+
? { ...meal, ...data }
|
|
255
|
+
: meal
|
|
256
|
+
)
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
console.log('Meal updated successfully');
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error('Failed to update meal:', error);
|
|
262
|
+
// Show error message to user
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### Delete Operation
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
const handleDeleteRow = async (row: Meal) => {
|
|
271
|
+
try {
|
|
272
|
+
// 1. Delete from database
|
|
273
|
+
const { error } = await supabase
|
|
274
|
+
.from('meals')
|
|
275
|
+
.delete()
|
|
276
|
+
.eq('meal_id', row.meal_id);
|
|
277
|
+
|
|
278
|
+
if (error) throw error;
|
|
279
|
+
|
|
280
|
+
// 2. Update local state - REMOVE the deleted row
|
|
281
|
+
setMeals(prevMeals =>
|
|
282
|
+
prevMeals.filter(meal => meal.meal_id !== row.meal_id)
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
console.log('Meal deleted successfully');
|
|
286
|
+
} catch (error) {
|
|
287
|
+
console.error('Failed to delete meal:', error);
|
|
288
|
+
// Show error message to user
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### Bulk Delete Operation
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const handleDeleteSelected = async (selectedRows: Record<string, boolean>) => {
|
|
297
|
+
try {
|
|
298
|
+
const selectedIds = Object.keys(selectedRows).filter(id => selectedRows[id]);
|
|
299
|
+
|
|
300
|
+
if (selectedIds.length === 0) return;
|
|
301
|
+
|
|
302
|
+
// 1. Delete from database
|
|
303
|
+
const { error } = await supabase
|
|
304
|
+
.from('meals')
|
|
305
|
+
.delete()
|
|
306
|
+
.in('meal_id', selectedIds);
|
|
307
|
+
|
|
308
|
+
if (error) throw error;
|
|
309
|
+
|
|
310
|
+
// 2. Update local state - REMOVE all selected rows
|
|
311
|
+
setMeals(prevMeals =>
|
|
312
|
+
prevMeals.filter(meal => !selectedIds.includes(meal.meal_id))
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// 3. Clear selection
|
|
316
|
+
setSelectedRows({});
|
|
317
|
+
|
|
318
|
+
console.log(`${selectedIds.length} meals deleted successfully`);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error('Failed to delete selected meals:', error);
|
|
321
|
+
// Show error message to user
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Common Patterns
|
|
327
|
+
|
|
328
|
+
#### Optimistic Updates
|
|
329
|
+
|
|
330
|
+
For better UX, update the UI immediately and rollback on error:
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
const handleDeleteRow = async (row: Meal) => {
|
|
334
|
+
// 1. Optimistically update UI first
|
|
335
|
+
const originalMeals = meals;
|
|
336
|
+
setMeals(prevMeals =>
|
|
337
|
+
prevMeals.filter(meal => meal.meal_id !== row.meal_id)
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
// 2. Delete from database
|
|
342
|
+
const { error } = await supabase
|
|
343
|
+
.from('meals')
|
|
344
|
+
.delete()
|
|
345
|
+
.eq('meal_id', row.meal_id);
|
|
346
|
+
|
|
347
|
+
if (error) throw error;
|
|
348
|
+
|
|
349
|
+
console.log('Meal deleted successfully');
|
|
350
|
+
} catch (error) {
|
|
351
|
+
// 3. Rollback on error
|
|
352
|
+
setMeals(originalMeals);
|
|
353
|
+
console.error('Failed to delete meal:', error);
|
|
354
|
+
// Show error message to user
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
```
|
|
358
|
+
|
|
178
359
|
## Feature Configuration
|
|
179
360
|
|
|
180
361
|
The DataTable component uses a unified `features` prop to control all table functionality. This provides a consistent and intuitive way to enable or disable features.
|
|
@@ -1899,6 +2080,14 @@ const columns: DataTableColumn<User>[] = [
|
|
|
1899
2080
|
- **Debug selection state**: Add console logs to verify `onRowSelectionChange` is being called with correct data
|
|
1900
2081
|
- **Fallback option**: If you don't provide `onDeleteSelected`, the table will fall back to calling `onDeleteRow` for each selected row
|
|
1901
2082
|
|
|
2083
|
+
#### 8. CRUD operations work but UI doesn't update
|
|
2084
|
+
- **DataTable is controlled**: You must update your local state after database operations
|
|
2085
|
+
- **Missing state updates**: Add state updates after successful CRUD operations
|
|
2086
|
+
- **See examples above**: Check the CRUD Operations Implementation section for complete examples
|
|
2087
|
+
- **Common issue**: Delete works but row doesn't disappear - you need to filter it from state
|
|
2088
|
+
- **Common issue**: Create works but new row doesn't appear - you need to add it to state
|
|
2089
|
+
- **Common issue**: Edit works but changes don't show - you need to update the row in state
|
|
2090
|
+
|
|
1902
2091
|
### Debug Mode
|
|
1903
2092
|
|
|
1904
2093
|
Enable debug logging for DataTable issues:
|