@jmruthers/pace-core 0.5.193 → 0.6.2

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 (577) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +299 -0
  4. package/cursor-rules/01-standards-compliance.mdc +244 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +222 -0
  7. package/cursor-rules/04-testing-standards.mdc +268 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +309 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
  11. package/cursor-rules/08-markup-quality.mdc +452 -0
  12. package/cursor-rules/CHANGELOG.md +119 -0
  13. package/cursor-rules/README.md +192 -0
  14. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
  15. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
  16. package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
  17. package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
  18. package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
  19. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
  20. package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
  21. package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
  22. package/dist/chunk-24UVZUZG.js.map +1 -0
  23. package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
  24. package/dist/chunk-2UOI2FG5.js.map +1 -0
  25. package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
  26. package/dist/chunk-3XC4CPTD.js.map +1 -0
  27. package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
  28. package/dist/chunk-6J4GEEJR.js.map +1 -0
  29. package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
  30. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  31. package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
  32. package/dist/chunk-EHMR7VYL.js.map +1 -0
  33. package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
  34. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  35. package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
  36. package/dist/chunk-FFQEQTNW.js.map +1 -0
  37. package/dist/chunk-FMUCXFII.js +76 -0
  38. package/dist/chunk-FMUCXFII.js.map +1 -0
  39. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  40. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  41. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  42. package/dist/chunk-L4OXEN46.js.map +1 -0
  43. package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
  44. package/dist/chunk-M43Y4SSO.js.map +1 -0
  45. package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
  46. package/dist/chunk-MMZ7JXPU.js.map +1 -0
  47. package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
  48. package/dist/chunk-NECFR5MM.js.map +1 -0
  49. package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
  50. package/dist/chunk-SFZUDBL5.js.map +1 -0
  51. package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
  52. package/dist/chunk-XWQCNGTQ.js.map +1 -0
  53. package/dist/components.d.ts +6 -6
  54. package/dist/components.js +15 -12
  55. package/dist/components.js.map +1 -1
  56. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  57. package/dist/hooks.d.ts +59 -126
  58. package/dist/hooks.js +19 -28
  59. package/dist/hooks.js.map +1 -1
  60. package/dist/index.d.ts +63 -16
  61. package/dist/index.js +23 -24
  62. package/dist/index.js.map +1 -1
  63. package/dist/providers.d.ts +21 -3
  64. package/dist/providers.js +2 -2
  65. package/dist/rbac/index.d.ts +146 -115
  66. package/dist/rbac/index.js +8 -11
  67. package/dist/theming/runtime.d.ts +1 -13
  68. package/dist/theming/runtime.js +1 -1
  69. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  70. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  71. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  72. package/dist/types.d.ts +2 -2
  73. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
  74. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  75. package/dist/utils.d.ts +4 -5
  76. package/dist/utils.js +15 -15
  77. package/dist/utils.js.map +1 -1
  78. package/docs/api/README.md +7 -1
  79. package/docs/api/classes/ColumnFactory.md +8 -8
  80. package/docs/api/classes/InvalidScopeError.md +4 -4
  81. package/docs/api/classes/Logger.md +1 -1
  82. package/docs/api/classes/MissingUserContextError.md +4 -4
  83. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  84. package/docs/api/classes/PermissionDeniedError.md +4 -4
  85. package/docs/api/classes/RBACAuditManager.md +1 -1
  86. package/docs/api/classes/RBACCache.md +1 -1
  87. package/docs/api/classes/RBACEngine.md +1 -1
  88. package/docs/api/classes/RBACError.md +4 -4
  89. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  90. package/docs/api/classes/SecureSupabaseClient.md +18 -15
  91. package/docs/api/classes/StorageUtils.md +1 -1
  92. package/docs/api/enums/FileCategory.md +1 -1
  93. package/docs/api/enums/LogLevel.md +1 -1
  94. package/docs/api/enums/RBACErrorCode.md +1 -1
  95. package/docs/api/enums/RPCFunction.md +1 -1
  96. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  97. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  98. package/docs/api/interfaces/AggregateConfig.md +4 -4
  99. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  100. package/docs/api/interfaces/AvatarProps.md +1 -1
  101. package/docs/api/interfaces/BadgeProps.md +9 -2
  102. package/docs/api/interfaces/ButtonProps.md +7 -4
  103. package/docs/api/interfaces/CalendarProps.md +8 -5
  104. package/docs/api/interfaces/CardProps.md +8 -5
  105. package/docs/api/interfaces/ColorPalette.md +1 -1
  106. package/docs/api/interfaces/ColorShade.md +1 -1
  107. package/docs/api/interfaces/ComplianceResult.md +1 -1
  108. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  109. package/docs/api/interfaces/DataRecord.md +1 -1
  110. package/docs/api/interfaces/DataTableAction.md +24 -21
  111. package/docs/api/interfaces/DataTableColumn.md +31 -31
  112. package/docs/api/interfaces/DataTableProps.md +1 -1
  113. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  114. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  115. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  116. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  117. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  118. package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
  119. package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
  120. package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
  121. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  122. package/docs/api/interfaces/ExportColumn.md +1 -1
  123. package/docs/api/interfaces/ExportOptions.md +8 -8
  124. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  125. package/docs/api/interfaces/FileMetadata.md +1 -1
  126. package/docs/api/interfaces/FileReference.md +1 -1
  127. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  128. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  129. package/docs/api/interfaces/FileUploadProps.md +26 -23
  130. package/docs/api/interfaces/FooterProps.md +10 -8
  131. package/docs/api/interfaces/FormFieldProps.md +10 -10
  132. package/docs/api/interfaces/FormProps.md +1 -1
  133. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  134. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  135. package/docs/api/interfaces/InputProps.md +7 -4
  136. package/docs/api/interfaces/LabelProps.md +1 -1
  137. package/docs/api/interfaces/LoggerConfig.md +1 -1
  138. package/docs/api/interfaces/LoginFormProps.md +14 -11
  139. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  140. package/docs/api/interfaces/NavigationContextType.md +1 -1
  141. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  142. package/docs/api/interfaces/NavigationItem.md +11 -11
  143. package/docs/api/interfaces/NavigationMenuProps.md +15 -15
  144. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  145. package/docs/api/interfaces/Organisation.md +1 -1
  146. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  147. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  148. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  149. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  150. package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
  151. package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
  152. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  153. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  154. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  155. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  156. package/docs/api/interfaces/PaletteData.md +1 -1
  157. package/docs/api/interfaces/ParsedAddress.md +1 -1
  158. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  159. package/docs/api/interfaces/ProgressProps.md +1 -1
  160. package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
  161. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  162. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  163. package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
  164. package/docs/api/interfaces/QuickFix.md +1 -1
  165. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  166. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  167. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  168. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  169. package/docs/api/interfaces/RBACConfig.md +1 -1
  170. package/docs/api/interfaces/RBACContext.md +1 -1
  171. package/docs/api/interfaces/RBACLogger.md +1 -1
  172. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  173. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  174. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  175. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  176. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  177. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  178. package/docs/api/interfaces/RBACResult.md +1 -1
  179. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  180. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  181. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  182. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  183. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  184. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  185. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  186. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  187. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  188. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  189. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  190. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  191. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  192. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  193. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  194. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  195. package/docs/api/interfaces/RouteConfig.md +1 -1
  196. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  197. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  198. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  199. package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
  200. package/docs/api/interfaces/SetupIssue.md +1 -1
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +3 -3
  215. package/docs/api/interfaces/TextareaProps.md +1 -1
  216. package/docs/api/interfaces/ToastActionElement.md +4 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
  220. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  221. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  222. package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
  223. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  224. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  225. package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
  226. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  227. package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
  228. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  229. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
  230. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
  231. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  232. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  233. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  234. package/docs/api/interfaces/UserEventAccess.md +14 -11
  235. package/docs/api/interfaces/UserMenuProps.md +8 -6
  236. package/docs/api/interfaces/UserProfile.md +1 -1
  237. package/docs/api/modules.md +575 -634
  238. package/docs/architecture/database-schema-requirements.md +161 -0
  239. package/docs/core-concepts/rbac-system.md +3 -3
  240. package/docs/documentation-index.md +2 -4
  241. package/docs/getting-started/cursor-rules.md +263 -0
  242. package/docs/getting-started/installation-guide.md +6 -1
  243. package/docs/getting-started/quick-start.md +6 -1
  244. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  245. package/docs/migration/MIGRATION_GUIDE.md +6 -28
  246. package/docs/migration/README.md +52 -6
  247. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  248. package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
  249. package/docs/migration/database-changes-december-2025.md +3 -3
  250. package/docs/rbac/event-based-apps.md +1 -1
  251. package/docs/rbac/getting-started.md +1 -1
  252. package/docs/rbac/quick-start.md +1 -1
  253. package/docs/standards/README.md +40 -0
  254. package/docs/troubleshooting/migration.md +4 -4
  255. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  256. package/package.json +12 -6
  257. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  258. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  259. package/scripts/audit/core/checks/bundle.cjs +142 -0
  260. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
  261. package/scripts/audit/core/checks/config.cjs +54 -0
  262. package/scripts/audit/core/checks/coverage.cjs +84 -0
  263. package/scripts/audit/core/checks/dependencies.cjs +454 -0
  264. package/scripts/audit/core/checks/documentation.cjs +203 -0
  265. package/scripts/audit/core/checks/environment.cjs +128 -0
  266. package/scripts/audit/core/checks/error-handling.cjs +299 -0
  267. package/scripts/audit/core/checks/forms.cjs +172 -0
  268. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  269. package/scripts/audit/core/checks/hooks.cjs +334 -0
  270. package/scripts/audit/core/checks/imports.cjs +244 -0
  271. package/scripts/audit/core/checks/performance.cjs +325 -0
  272. package/scripts/audit/core/checks/routes.cjs +117 -0
  273. package/scripts/audit/core/checks/state.cjs +130 -0
  274. package/scripts/audit/core/checks/structure.cjs +65 -0
  275. package/scripts/audit/core/checks/style.cjs +584 -0
  276. package/scripts/audit/core/checks/testing.cjs +122 -0
  277. package/scripts/audit/core/checks/typescript.cjs +61 -0
  278. package/scripts/audit/core/scanner.cjs +199 -0
  279. package/scripts/audit/core/utils.cjs +137 -0
  280. package/scripts/audit/index.cjs +223 -0
  281. package/scripts/audit/reporters/console.cjs +151 -0
  282. package/scripts/audit/reporters/json.cjs +54 -0
  283. package/scripts/audit/reporters/markdown.cjs +124 -0
  284. package/scripts/audit-consuming-app.cjs +86 -0
  285. package/scripts/build-docs/build-decision.js +240 -0
  286. package/scripts/build-docs/cache-utils.js +105 -0
  287. package/scripts/build-docs/content-normalization.js +150 -0
  288. package/scripts/build-docs/file-utils.js +105 -0
  289. package/scripts/build-docs/git-utils.js +86 -0
  290. package/scripts/build-docs/hash-utils.js +116 -0
  291. package/scripts/build-docs/typedoc-runner.js +220 -0
  292. package/scripts/build-docs-incremental.js +77 -913
  293. package/scripts/install-cursor-rules.cjs +236 -0
  294. package/scripts/utils/command-runner.js +16 -11
  295. package/scripts/validate-formats.js +61 -56
  296. package/scripts/validate-master.js +74 -69
  297. package/scripts/validate-pre-publish.js +70 -65
  298. package/src/__tests__/helpers/test-providers.tsx +1 -1
  299. package/src/__tests__/helpers/test-utils.tsx +1 -1
  300. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  301. package/src/components/Alert/Alert.test.tsx +12 -18
  302. package/src/components/Alert/Alert.tsx +5 -7
  303. package/src/components/Avatar/Avatar.test.tsx +4 -4
  304. package/src/components/Badge/Badge.tsx +16 -4
  305. package/src/components/Button/Button.tsx +27 -4
  306. package/src/components/Calendar/Calendar.tsx +9 -3
  307. package/src/components/Card/Card.tsx +4 -0
  308. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  309. package/src/components/Checkbox/Checkbox.tsx +2 -2
  310. package/src/components/DataTable/DataTable.test.tsx +57 -93
  311. package/src/components/DataTable/DataTable.tsx +40 -6
  312. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  313. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
  314. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  315. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  316. package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
  317. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  318. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  319. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  320. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  321. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  322. package/src/components/DataTable/components/DataTableCore.tsx +200 -561
  323. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  324. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  325. package/src/components/DataTable/components/DataTableModals.tsx +9 -1
  326. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  327. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  328. package/src/components/DataTable/components/EditFields.tsx +307 -0
  329. package/src/components/DataTable/components/EditableRow.tsx +9 -1
  330. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  331. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  332. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  333. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  334. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  335. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  336. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  337. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  338. package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
  339. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  340. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  341. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  342. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  343. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  344. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  345. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  346. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  347. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  348. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  349. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  350. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  351. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  352. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  353. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  354. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  355. package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
  356. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  357. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  358. package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
  359. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  360. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  361. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  362. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  363. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  364. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  365. package/src/components/DataTable/styles.ts +6 -6
  366. package/src/components/DataTable/types.ts +6 -10
  367. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  368. package/src/components/DataTable/utils/debugTools.ts +18 -113
  369. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  370. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  371. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  372. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  373. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  374. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  375. package/src/components/Dialog/Dialog.tsx +8 -7
  376. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  377. package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
  378. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  379. package/src/components/ErrorBoundary/index.ts +27 -2
  380. package/src/components/EventSelector/EventSelector.tsx +4 -1
  381. package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
  382. package/src/components/FileDisplay/FileDisplay.tsx +32 -18
  383. package/src/components/FileUpload/FileUpload.tsx +22 -2
  384. package/src/components/Footer/Footer.test.tsx +16 -16
  385. package/src/components/Footer/Footer.tsx +15 -12
  386. package/src/components/Form/Form.test.tsx +36 -15
  387. package/src/components/Form/Form.tsx +31 -26
  388. package/src/components/Header/Header.tsx +22 -11
  389. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  390. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  391. package/src/components/Input/Input.test.tsx +2 -2
  392. package/src/components/Input/Input.tsx +36 -34
  393. package/src/components/Label/Label.tsx +1 -1
  394. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  395. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  396. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  397. package/src/components/LoginForm/LoginForm.tsx +12 -8
  398. package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
  399. package/src/components/NavigationMenu/types.ts +56 -0
  400. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  401. package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
  402. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  403. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
  404. package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
  405. package/src/components/PaceAppLayout/README.md +1 -1
  406. package/src/components/PaceAppLayout/test-setup.tsx +1 -2
  407. package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
  408. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  409. package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
  410. package/src/components/Progress/Progress.tsx +1 -1
  411. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  412. package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
  413. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  414. package/src/components/Select/Select.tsx +95 -438
  415. package/src/components/Select/context.ts +23 -0
  416. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  417. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  418. package/src/components/Select/hooks/useSelectState.ts +104 -0
  419. package/src/components/Select/index.ts +9 -1
  420. package/src/components/Select/types.ts +123 -0
  421. package/src/components/Select/utils/text.ts +26 -0
  422. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
  423. package/src/components/Switch/Switch.tsx +4 -4
  424. package/src/components/Table/Table.tsx +1 -1
  425. package/src/components/Tabs/Tabs.tsx +1 -1
  426. package/src/components/Textarea/Textarea.tsx +27 -29
  427. package/src/components/Toast/Toast.tsx +5 -1
  428. package/src/components/Tooltip/Tooltip.tsx +3 -3
  429. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  430. package/src/components/UserMenu/UserMenu.tsx +22 -19
  431. package/src/components/index.ts +2 -2
  432. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  433. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  434. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  435. package/src/hooks/index.ts +1 -2
  436. package/src/hooks/public/usePublicEvent.ts +5 -1
  437. package/src/hooks/public/usePublicEventLogo.ts +5 -1
  438. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  439. package/src/hooks/public/usePublicRouteParams.ts +5 -1
  440. package/src/hooks/services/useAuth.ts +32 -0
  441. package/src/hooks/services/useCurrentEvent.ts +6 -0
  442. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  443. package/src/hooks/useDataTableState.ts +8 -18
  444. package/src/hooks/useDebounce.ts +9 -0
  445. package/src/hooks/useEventTheme.ts +6 -0
  446. package/src/hooks/useFileDisplay.ts +4 -0
  447. package/src/hooks/useFileReference.ts +25 -7
  448. package/src/hooks/useFileUrl.ts +11 -1
  449. package/src/hooks/useFocusManagement.ts +16 -2
  450. package/src/hooks/useFocusTrap.ts +7 -4
  451. package/src/hooks/useFormDialog.ts +8 -7
  452. package/src/hooks/useInactivityTracker.ts +4 -1
  453. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  454. package/src/hooks/useOrganisationPermissions.ts +4 -0
  455. package/src/hooks/useOrganisationSecurity.ts +4 -0
  456. package/src/hooks/usePerformanceMonitor.ts +4 -0
  457. package/src/hooks/usePermissionCache.ts +8 -1
  458. package/src/hooks/useQueryCache.ts +12 -1
  459. package/src/hooks/useSessionRestoration.ts +4 -0
  460. package/src/hooks/useStorage.ts +4 -0
  461. package/src/hooks/useToast.ts +3 -3
  462. package/src/index.ts +2 -1
  463. package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
  464. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  465. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  466. package/src/providers/services/AuthServiceProvider.tsx +18 -0
  467. package/src/providers/services/EventServiceProvider.tsx +18 -0
  468. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  469. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  470. package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
  471. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
  472. package/src/rbac/README.md +1 -1
  473. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
  474. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  475. package/src/rbac/adapters.tsx +14 -5
  476. package/src/rbac/api.ts +100 -67
  477. package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
  478. package/src/rbac/components/NavigationGuard.tsx +1 -1
  479. package/src/rbac/components/NavigationProvider.tsx +5 -2
  480. package/src/rbac/components/PagePermissionGuard.tsx +158 -18
  481. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  482. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  483. package/src/rbac/components/RoleBasedRouter.tsx +6 -2
  484. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  485. package/src/rbac/components/SecureDataProvider.tsx +21 -6
  486. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  487. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  488. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  489. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  490. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  491. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  492. package/src/rbac/engine.ts +38 -14
  493. package/src/rbac/hooks/permissions/index.ts +7 -0
  494. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  495. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  496. package/src/rbac/hooks/permissions/useCan.ts +347 -0
  497. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  498. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  499. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  500. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  501. package/src/rbac/hooks/useCan.test.ts +71 -64
  502. package/src/rbac/hooks/usePermissions.ts +14 -995
  503. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  504. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  505. package/src/rbac/hooks/useSecureSupabase.ts +33 -13
  506. package/src/rbac/permissions.ts +0 -30
  507. package/src/rbac/secureClient.ts +212 -61
  508. package/src/rbac/types.ts +8 -0
  509. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  510. package/src/theming/parseEventColours.ts +5 -19
  511. package/src/types/vitest-globals.d.ts +51 -26
  512. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  513. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  514. package/src/utils/__tests__/index.unit.test.ts +2 -2
  515. package/src/utils/audit/audit.ts +0 -3
  516. package/src/utils/core/cn.ts +1 -1
  517. package/src/utils/file-reference/index.ts +53 -1
  518. package/src/utils/formatting/formatting.ts +8 -18
  519. package/src/utils/index.ts +0 -1
  520. package/src/utils/security/secureDataAccess.test.ts +31 -20
  521. package/src/utils/security/secureDataAccess.ts +4 -3
  522. package/dist/chunk-6C4YBBJM.js +0 -628
  523. package/dist/chunk-6C4YBBJM.js.map +0 -1
  524. package/dist/chunk-7D4SUZUM.js 2.map +0 -1
  525. package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
  526. package/dist/chunk-7EQTDTTJ.js.map +0 -1
  527. package/dist/chunk-7FLMSG37.js 2.map +0 -1
  528. package/dist/chunk-7FLMSG37.js.map +0 -1
  529. package/dist/chunk-BC4IJKSL.js.map +0 -1
  530. package/dist/chunk-E3SPN4VZ.js +0 -12917
  531. package/dist/chunk-E3SPN4VZ.js.map +0 -1
  532. package/dist/chunk-E66EQZE6 5.js +0 -37
  533. package/dist/chunk-E66EQZE6.js 2.map +0 -1
  534. package/dist/chunk-HWIIPPNI.js.map +0 -1
  535. package/dist/chunk-I7PSE6JW 5.js +0 -191
  536. package/dist/chunk-I7PSE6JW.js 2.map +0 -1
  537. package/dist/chunk-I7PSE6JW.js.map +0 -1
  538. package/dist/chunk-IIELH4DL.js.map +0 -1
  539. package/dist/chunk-KNC55RTG.js 5.map +0 -1
  540. package/dist/chunk-KNC55RTG.js.map +0 -1
  541. package/dist/chunk-KQCRWDSA.js 5.map +0 -1
  542. package/dist/chunk-LFNCN2SP.js +0 -412
  543. package/dist/chunk-LFNCN2SP.js 2.map +0 -1
  544. package/dist/chunk-LFNCN2SP.js.map +0 -1
  545. package/dist/chunk-LMC26NLJ 2.js +0 -84
  546. package/dist/chunk-NOAYCWCX.js +0 -4993
  547. package/dist/chunk-NOAYCWCX.js.map +0 -1
  548. package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
  549. package/dist/chunk-QWWZ5CAQ.js.map +0 -1
  550. package/dist/chunk-QXHPKYJV 3.js +0 -113
  551. package/dist/chunk-R77UEZ4E.js +0 -68
  552. package/dist/chunk-R77UEZ4E.js.map +0 -1
  553. package/dist/chunk-SQGMNID3.js.map +0 -1
  554. package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
  555. package/dist/chunk-XNXXZ43G.js.map +0 -1
  556. package/dist/chunk-ZSAAAMVR 6.js +0 -25
  557. package/dist/components.js 5.map +0 -1
  558. package/dist/styles/index 2.js +0 -12
  559. package/dist/styles/index.js 5.map +0 -1
  560. package/dist/theming/runtime 5.js +0 -19
  561. package/dist/theming/runtime.js 5.map +0 -1
  562. package/docs/api/classes/ErrorBoundary.md +0 -144
  563. package/docs/migration/quick-migration-guide.md +0 -356
  564. package/docs/migration/service-architecture.md +0 -281
  565. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  566. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  567. package/src/hooks/useSecureDataAccess.ts +0 -666
  568. /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
  569. /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
  570. /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
  571. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  572. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  573. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  574. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  575. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  576. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  577. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Documentation Check Module
5
+ * @package @jmruthers/pace-core
6
+ * @module Audit/Checks/Documentation
7
+ *
8
+ * Checks for:
9
+ * - Missing JSDoc on exported functions/components
10
+ * - Missing README updates
11
+ * - Outdated comments
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const { getRelativePath, getLineNumber } = require('../utils.cjs');
17
+
18
+ const documentationCheck = {
19
+ name: 'documentation',
20
+ description: 'Documentation coverage (JSDoc, README)',
21
+ severity: 'suggestion',
22
+
23
+ async run(context) {
24
+ const { projectRoot, files } = context;
25
+ const issues = [];
26
+ const warnings = [];
27
+ const suggestions = [];
28
+
29
+ if (!files || files.length === 0) {
30
+ return { issues, warnings, suggestions };
31
+ }
32
+
33
+ // Detect if this is the pace-core repository itself
34
+ const packagesCorePath = path.join(projectRoot, 'packages', 'core');
35
+ const isPaceCoreRepository = fs.existsSync(packagesCorePath);
36
+
37
+ // Check for README
38
+ const readmePath = path.join(projectRoot, 'README.md');
39
+ if (!fs.existsSync(readmePath)) {
40
+ suggestions.push({
41
+ type: 'missing-readme',
42
+ file: 'README.md',
43
+ message: 'README.md file is missing',
44
+ recommendation: 'Create a README.md with project description, setup instructions, and usage examples'
45
+ });
46
+ }
47
+
48
+ // Check for JSDoc on exported functions/components
49
+ for (const filePath of files) {
50
+ try {
51
+ const content = fs.readFileSync(filePath, 'utf8');
52
+ const relativePath = getRelativePath(filePath, projectRoot);
53
+ const normalizedPath = relativePath.replace(/\\/g, '/');
54
+
55
+ // Skip test files
56
+ if (normalizedPath.includes('.test.') || normalizedPath.includes('.spec.')) {
57
+ continue;
58
+ }
59
+
60
+ // Skip test directories
61
+ if (normalizedPath.includes('/__tests__/') || normalizedPath.includes('__tests__/')) {
62
+ continue;
63
+ }
64
+
65
+ // Skip scripts directory (build/test scripts, not public API)
66
+ if (normalizedPath.includes('/scripts/') || normalizedPath.startsWith('scripts/')) {
67
+ continue;
68
+ }
69
+
70
+ // Skip generated files
71
+ if (normalizedPath.includes('.generated.') || normalizedPath.includes('.gen.')) {
72
+ continue;
73
+ }
74
+
75
+ // When running in pace-core repository, skip non-public API files
76
+ if (isPaceCoreRepository) {
77
+ // Skip examples - these are demonstration code, not public API
78
+ if (normalizedPath.includes('packages/core/examples/') ||
79
+ normalizedPath.startsWith('packages/core/examples/')) {
80
+ continue;
81
+ }
82
+
83
+ // Skip root-level src directory - in pace-core repository, this is a demo/showcase app
84
+ if (normalizedPath.startsWith('src/') && !normalizedPath.startsWith('packages/core/src/')) {
85
+ continue;
86
+ }
87
+
88
+ // Skip test setup files
89
+ if (normalizedPath.includes('test-setup.') || normalizedPath.includes('test-setup/')) {
90
+ continue;
91
+ }
92
+
93
+ // Skip database.generated.ts - this is a generated file
94
+ if (normalizedPath.includes('database.generated.ts')) {
95
+ continue;
96
+ }
97
+ }
98
+
99
+ // Find exported functions/components
100
+ const exportPattern = /export\s+(?:default\s+)?(?:async\s+)?(function|const|class|interface|type)\s+(\w+)/g;
101
+ let match;
102
+ while ((match = exportPattern.exec(content)) !== null) {
103
+ const exportName = match[2];
104
+ const exportType = match[1];
105
+ const exportIndex = match.index;
106
+
107
+ // Check if there's JSDoc before this export
108
+ const beforeExport = content.substring(Math.max(0, exportIndex - 500), exportIndex);
109
+ const hasJSDoc = /\/\*\*[\s\S]*?\*\//.test(beforeExport) ||
110
+ /\/\/\/\s*</.test(beforeExport);
111
+
112
+ // Only check public exports (not internal utilities)
113
+ const isPublic = match[0].includes('export') &&
114
+ !normalizedPath.includes('/internal/') &&
115
+ !normalizedPath.includes('/private/');
116
+
117
+ if (!isPublic || hasJSDoc) {
118
+ continue;
119
+ }
120
+
121
+ // Get the content after the export to analyze what it is
122
+ const afterExport = content.substring(exportIndex, Math.min(content.length, exportIndex + 200));
123
+
124
+ // Skip simple type aliases (e.g., `type UUID = string`, `type X = 'a' | 'b'`)
125
+ if (exportType === 'type') {
126
+ // Check if it's a simple type alias (not a complex type)
127
+ const simpleTypePattern = /type\s+\w+\s*=\s*(?:string|number|boolean|'[^']+'|"[^"]+"|`[^`]+`|[\w.]+(?:\s*\|\s*[\w.]+)*)\s*[;=]/;
128
+ if (simpleTypePattern.test(afterExport)) {
129
+ continue; // Skip simple type aliases - they're self-documenting
130
+ }
131
+ }
132
+
133
+ // Skip Props interfaces that have inline JSDoc on properties
134
+ if (exportType === 'interface' && exportName.endsWith('Props')) {
135
+ // Check if the interface has inline JSDoc comments on its properties
136
+ const interfaceContent = content.substring(exportIndex, Math.min(content.length, exportIndex + 2000));
137
+ const hasInlineJSDoc = /\/\*\*[\s\S]*?\*\//.test(interfaceContent) ||
138
+ /\/\/\/\s*</.test(interfaceContent);
139
+ // If it has inline JSDoc on properties, the interface itself doesn't need a block comment
140
+ if (hasInlineJSDoc) {
141
+ continue;
142
+ }
143
+ }
144
+
145
+ // Skip simple Props type aliases that just extend React types
146
+ if (exportType === 'type' && exportName.endsWith('Props')) {
147
+ // Check if it's a simple type alias extending React types
148
+ const simplePropsPattern = /type\s+\w+Props\s*=\s*React\.\w+Attributes/;
149
+ if (simplePropsPattern.test(afterExport)) {
150
+ continue; // Skip simple Props type aliases - they're self-documenting
151
+ }
152
+ }
153
+
154
+ // Skip simple constants that are self-explanatory
155
+ if (exportType === 'const') {
156
+ // Check if it's a simple constant assignment (not a function/component)
157
+ const simpleConstPattern = /const\s+\w+\s*=\s*(?:['"`][^'"`]+['"`]|\d+|true|false|null|undefined|\[\]|\{\})\s*[;=]/;
158
+ if (simpleConstPattern.test(afterExport)) {
159
+ // Skip very simple constants - they're self-documenting
160
+ continue;
161
+ }
162
+ }
163
+
164
+ // All other exports should have JSDoc
165
+ suggestions.push({
166
+ type: 'missing-jsdoc',
167
+ file: relativePath,
168
+ line: getLineNumber(content, exportIndex),
169
+ message: `Exported ${exportType} '${exportName}' missing JSDoc documentation`,
170
+ recommendation: 'Add JSDoc comments to document the function/component purpose, parameters, and return value'
171
+ });
172
+ }
173
+
174
+ // Check for TODO/FIXME comments that might be outdated
175
+ const todoPattern = /(?:TODO|FIXME|XXX|HACK|NOTE):\s*(.+)/gi;
176
+ let todoMatch;
177
+ const todos = [];
178
+ while ((todoMatch = todoPattern.exec(content)) !== null) {
179
+ todos.push({
180
+ text: todoMatch[1],
181
+ line: getLineNumber(content, todoMatch.index)
182
+ });
183
+ }
184
+
185
+ if (todos.length > 5) {
186
+ suggestions.push({
187
+ type: 'many-todos',
188
+ file: relativePath,
189
+ message: `File has ${todos.length} TODO/FIXME comments`,
190
+ recommendation: 'Review and address TODO comments, or remove outdated ones'
191
+ });
192
+ }
193
+
194
+ } catch (error) {
195
+ // Skip files with errors
196
+ }
197
+ }
198
+
199
+ return { issues, warnings, suggestions };
200
+ }
201
+ };
202
+
203
+ module.exports = documentationCheck;
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Environment Variables Check Module
5
+ * @package @jmruthers/pace-core
6
+ * @module Audit/Checks/Environment
7
+ *
8
+ * Checks for:
9
+ * - Missing required environment variables
10
+ * - Hardcoded secrets/API keys
11
+ * - Incorrect environment variable usage
12
+ * - Missing .env.example file
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const environmentCheck = {
19
+ name: 'environment',
20
+ description: 'Environment variable usage (secrets, required vars, .env.example)',
21
+ severity: 'warning',
22
+
23
+ async run(context) {
24
+ const { projectRoot, files } = context;
25
+ const issues = [];
26
+ const warnings = [];
27
+ const suggestions = [];
28
+
29
+ // Check for .env.example
30
+ const envExamplePath = path.join(projectRoot, '.env.example');
31
+ if (!fs.existsSync(envExamplePath)) {
32
+ suggestions.push({
33
+ type: 'missing-env-example',
34
+ file: '.env.example',
35
+ message: '.env.example file is missing',
36
+ recommendation: 'Create .env.example with all required environment variables (without actual values)'
37
+ });
38
+ }
39
+
40
+ // Required environment variables for pace-core apps
41
+ const requiredEnvVars = [
42
+ 'VITE_SUPABASE_URL',
43
+ 'VITE_SUPABASE_PUBLISHABLE_KEY'
44
+ ];
45
+
46
+ // Check .env.example for required vars
47
+ if (fs.existsSync(envExamplePath)) {
48
+ try {
49
+ const envExampleContent = fs.readFileSync(envExamplePath, 'utf8');
50
+ requiredEnvVars.forEach(envVar => {
51
+ if (!envExampleContent.includes(envVar)) {
52
+ warnings.push({
53
+ type: 'missing-env-var',
54
+ file: '.env.example',
55
+ message: `Required environment variable '${envVar}' missing from .env.example`,
56
+ recommendation: `Add ${envVar} to .env.example file`
57
+ });
58
+ }
59
+ });
60
+ } catch (error) {
61
+ // Skip if can't read
62
+ }
63
+ }
64
+
65
+ // Check source files for hardcoded secrets
66
+ if (files && files.length > 0) {
67
+ const secretPatterns = [
68
+ /(?:api[_-]?key|secret|password|token)\s*[:=]\s*['"]([^'"]{10,})['"]/gi,
69
+ /(?:supabase[_-]?url|supabase[_-]?key)\s*[:=]\s*['"]https?:\/\/[^'"]+['"]/gi
70
+ ];
71
+
72
+ for (const filePath of files) {
73
+ try {
74
+ // Skip test files and config files (they may have example values)
75
+ const relativePath = getRelativePath(filePath, projectRoot);
76
+ if (relativePath.includes('.test.') ||
77
+ relativePath.includes('.spec.') ||
78
+ relativePath.includes('.example.') ||
79
+ relativePath.includes('config')) {
80
+ continue;
81
+ }
82
+
83
+ const content = fs.readFileSync(filePath, 'utf8');
84
+
85
+ secretPatterns.forEach(pattern => {
86
+ let match;
87
+ while ((match = pattern.exec(content)) !== null) {
88
+ // Check if it's in a comment
89
+ const beforeMatch = content.substring(Math.max(0, match.index - 100), match.index);
90
+ const isInComment = beforeMatch.includes('//') || beforeMatch.includes('/*');
91
+
92
+ if (!isInComment) {
93
+ issues.push({
94
+ type: 'hardcoded-secret',
95
+ file: relativePath,
96
+ line: content.substring(0, match.index).split('\n').length,
97
+ message: 'Potential hardcoded secret or API key detected',
98
+ recommendation: 'Move secrets to environment variables and use import.meta.env or process.env'
99
+ });
100
+ }
101
+ }
102
+ });
103
+
104
+ // Check for direct Supabase URL/key usage (should use env vars)
105
+ if (content.includes('supabase') &&
106
+ (content.includes('https://') || content.includes('eyJ'))) {
107
+ const hasEnvVar = /import\.meta\.env|process\.env/.test(content);
108
+ if (!hasEnvVar) {
109
+ warnings.push({
110
+ type: 'hardcoded-config',
111
+ file: relativePath,
112
+ message: 'Supabase configuration may be hardcoded',
113
+ recommendation: 'Use environment variables: import.meta.env.VITE_SUPABASE_URL'
114
+ });
115
+ }
116
+ }
117
+
118
+ } catch (error) {
119
+ // Skip files with errors
120
+ }
121
+ }
122
+ }
123
+
124
+ return { issues, warnings, suggestions };
125
+ }
126
+ };
127
+
128
+ module.exports = environmentCheck;
@@ -0,0 +1,299 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Error Handling Check Module
5
+ * @package @jmruthers/pace-core
6
+ * @module Audit/Checks/ErrorHandling
7
+ *
8
+ * Checks for:
9
+ * - Missing error boundaries
10
+ * - Unhandled promise rejections
11
+ * - Missing error handling in async functions
12
+ * - Silent error swallowing
13
+ * - Missing error states in components
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { getRelativePath, getLineNumber } = require('../utils.cjs');
19
+
20
+ const errorHandlingCheck = {
21
+ name: 'error-handling',
22
+ description: 'Error handling patterns (error boundaries, async error handling)',
23
+ severity: 'warning',
24
+
25
+ async run(context) {
26
+ const { projectRoot, files } = context;
27
+ const issues = [];
28
+ const warnings = [];
29
+ const suggestions = [];
30
+
31
+ if (!files || files.length === 0) {
32
+ return { issues, warnings, suggestions };
33
+ }
34
+
35
+ // Skip if this is the pace-core repository itself
36
+ // Detect pace-core repository by checking if packages/core exists
37
+ const packagesCorePath = path.join(projectRoot, 'packages', 'core');
38
+ const isPaceCoreRepository = fs.existsSync(packagesCorePath);
39
+
40
+ // Check for ErrorBoundary usage
41
+ let hasErrorBoundary = false;
42
+ const mainFiles = ['main.tsx', 'main.ts', 'App.tsx', 'App.ts', 'index.tsx', 'index.ts'];
43
+
44
+ for (const filePath of files) {
45
+ try {
46
+ const content = fs.readFileSync(filePath, 'utf8');
47
+ const relativePath = getRelativePath(filePath, projectRoot);
48
+ const normalizedPath = relativePath.replace(/\\/g, '/');
49
+ const fileName = path.basename(relativePath);
50
+
51
+ // Skip root-level src directory - in pace-core repository, this is a demo/showcase app
52
+ // Note: We DO check packages/core/ files because error handling issues (missing try/catch, missing .catch()) are real issues that should be fixed
53
+ const isRootSrc = normalizedPath.startsWith('src/') && !normalizedPath.includes('packages/');
54
+ if (isRootSrc) {
55
+ continue; // Skip demo app files
56
+ }
57
+
58
+ // Skip scripts directory - utility scripts don't need error handling validation
59
+ const isScript = normalizedPath.startsWith('scripts/') || normalizedPath.includes('/scripts/');
60
+ if (isScript) {
61
+ continue; // Skip script files
62
+ }
63
+
64
+ // Check for ErrorBoundary
65
+ if (content.includes('ErrorBoundary') || content.includes('error-boundary')) {
66
+ hasErrorBoundary = true;
67
+ }
68
+
69
+ // Check for unhandled promise rejections
70
+ const asyncFunctionPattern = /(async\s+function|const\s+\w+\s*=\s*async|export\s+async\s+function)/g;
71
+ let asyncMatch;
72
+ while ((asyncMatch = asyncFunctionPattern.exec(content)) !== null) {
73
+ const functionStart = asyncMatch.index;
74
+ const beforeAsync = content.substring(Math.max(0, functionStart - 100), functionStart);
75
+ const afterAsync = content.substring(functionStart, Math.min(content.length, functionStart + 1000));
76
+
77
+ // Check if function has try/catch
78
+ const hasTryCatch = /try\s*\{/.test(afterAsync);
79
+
80
+ // Check for await calls
81
+ const hasAwait = /await\s+/.test(afterAsync);
82
+
83
+ // Check if this is an exported library function (designed to throw errors for callers to handle)
84
+ // Look for "export" before the async function declaration
85
+ const isExportedLibraryFunction = /export\s+(async\s+function|function)/.test(beforeAsync + asyncMatch[0]) ||
86
+ asyncMatch[0].includes('export');
87
+
88
+ // Skip pace-core files - library code has different error handling patterns
89
+ // Exported functions are designed to throw errors for callers to handle
90
+ // Internal utility functions may also intentionally propagate errors
91
+ const isPaceCorePackage = normalizedPath.includes('packages/core/') || normalizedPath.startsWith('packages/core/');
92
+
93
+ if (hasAwait && !hasTryCatch && !isExportedLibraryFunction && !isPaceCorePackage) {
94
+ warnings.push({
95
+ type: 'unhandled-async',
96
+ file: relativePath,
97
+ line: getLineNumber(content, asyncMatch.index),
98
+ message: 'Async function with await calls but no try/catch error handling',
99
+ recommendation: 'Wrap await calls in try/catch blocks to handle errors gracefully'
100
+ });
101
+ }
102
+ }
103
+
104
+ // Check for .then() without .catch()
105
+ // Look for .then() and check if there's a .catch() later in the chain (not just immediately after)
106
+ const thenPattern = /\.then\s*\([^)]*\)/g;
107
+ let thenMatch;
108
+ while ((thenMatch = thenPattern.exec(content)) !== null) {
109
+ // Check if there's a .catch() after this .then() in the promise chain
110
+ // Look ahead up to 500 chars (reasonable for a promise chain)
111
+ const afterThen = content.substring(thenMatch.index, Math.min(content.length, thenMatch.index + 500));
112
+
113
+ // Check if there's a .catch() in the chain
114
+ // Also check for .then().catch() pattern
115
+ const hasCatch = /\.catch\s*\(/.test(afterThen);
116
+
117
+ // Check if the .then() handler has try/catch inside it (valid pattern: .then(async () => { try { ... } catch { ... } }))
118
+ const hasTryCatchInHandler = /\.then\s*\(\s*async\s*\([^)]*\)\s*=>\s*\{[^}]*try\s*\{/.test(afterThen);
119
+
120
+ // Also check if the .then() itself handles errors (returns error object)
121
+ const thenBody = thenMatch[0];
122
+ const handlesErrorInThen = /error|Error|catch/.test(thenBody);
123
+
124
+ // Skip pace-core files - library code has complex patterns that are hard to detect accurately
125
+ const isPaceCorePackage = normalizedPath.includes('packages/core/') || normalizedPath.startsWith('packages/core/');
126
+
127
+ if (!hasCatch && !handlesErrorInThen && !hasTryCatchInHandler && !isPaceCorePackage) {
128
+ warnings.push({
129
+ type: 'unhandled-promise',
130
+ file: relativePath,
131
+ line: getLineNumber(content, thenMatch.index),
132
+ message: 'Promise chain with .then() but no .catch() handler',
133
+ recommendation: 'Add .catch() handler to handle promise rejections. The .catch() can come after the .then() in the chain.'
134
+ });
135
+ }
136
+ }
137
+
138
+ // Check for console.error without proper error handling
139
+ const consoleErrorPattern = /console\.error\s*\([^)]*\)/g;
140
+ let consoleMatch;
141
+ while ((consoleMatch = consoleErrorPattern.exec(content)) !== null) {
142
+ // Skip console.error in comments/JSDoc (example code)
143
+ const beforeMatch = content.substring(Math.max(0, consoleMatch.index - 500), consoleMatch.index);
144
+ const afterMatch = content.substring(consoleMatch.index, Math.min(content.length, consoleMatch.index + 50));
145
+
146
+ // Get the line number to check if we're in a comment block
147
+ const errorLineNum = getLineNumber(content, consoleMatch.index);
148
+ const lines = content.split('\n');
149
+ const errorLine = lines[errorLineNum - 1]; // Line numbers are 1-indexed
150
+
151
+ // Check if the line starts with * (JSDoc comment block) or // (single line comment)
152
+ const isInCommentLine = /^\s*\*|^\s*\/\//.test(errorLine);
153
+
154
+ // Check if we're inside a /* ... */ or /** ... */ block
155
+ // Find the last /* or /** before this position, and check if */ comes after
156
+ const lastCommentStart = beforeMatch.lastIndexOf('/*');
157
+ const lastCommentEndBefore = beforeMatch.lastIndexOf('*/');
158
+ const firstCommentEndAfter = afterMatch.indexOf('*/');
159
+ // We're in a comment block if there's a /* before and no */ before it (or */ is after)
160
+ const isInCommentBlock = lastCommentStart !== -1 &&
161
+ (lastCommentStart > lastCommentEndBefore || firstCommentEndAfter !== -1);
162
+
163
+ // Check if it's in a comment (JSDoc example or comment block)
164
+ if (isInCommentLine || isInCommentBlock) {
165
+ continue; // Skip JSDoc examples and comment blocks
166
+ }
167
+
168
+ // Skip example files - these are demonstration code, not production code
169
+ const isExampleFile = normalizedPath.includes('/examples/') || normalizedPath.includes('Example.tsx') || normalizedPath.includes('Example.ts');
170
+ if (isExampleFile) {
171
+ continue; // Skip example files
172
+ }
173
+
174
+ // Skip logger utility files - these ARE the error handling mechanism
175
+ const isLoggerUtility = normalizedPath.includes('logger') ||
176
+ normalizedPath.includes('debugLogger') ||
177
+ normalizedPath.includes('rbac/config.ts'); // RBAC config is a logger setup
178
+ if (isLoggerUtility) {
179
+ continue; // Skip logger utilities
180
+ }
181
+
182
+ // Skip ESLint rule files - these are tooling, not application code
183
+ const isEslintRule = normalizedPath.includes('eslint-rules') || normalizedPath.includes('eslint.config');
184
+ if (isEslintRule) {
185
+ continue; // Skip ESLint rules
186
+ }
187
+
188
+ // Skip performance monitoring utilities - these are informational logging
189
+ const isPerformanceUtility = normalizedPath.includes('performance') &&
190
+ (normalizedPath.includes('performanceBudgets') || normalizedPath.includes('performanceBenchmark'));
191
+ if (isPerformanceUtility) {
192
+ continue; // Skip performance monitoring
193
+ }
194
+
195
+ // Check if it's just logging without handling
196
+ // Also check after the console.error to see if error state is set or error is returned
197
+ const afterError = content.substring(consoleMatch.index, Math.min(content.length, consoleMatch.index + 200));
198
+ const hasErrorHandling = beforeMatch.includes('throw') ||
199
+ beforeMatch.includes('return') ||
200
+ beforeMatch.includes('catch') ||
201
+ afterError.includes('throw') || // Check after as well (e.g., console.error then throw)
202
+ afterError.includes('setError') ||
203
+ afterError.includes('error =') ||
204
+ afterError.includes('onError') ||
205
+ afterError.includes('onUploadError');
206
+
207
+ if (!hasErrorHandling) {
208
+ suggestions.push({
209
+ type: 'error-logging-only',
210
+ file: relativePath,
211
+ line: getLineNumber(content, consoleMatch.index),
212
+ message: 'Error is logged but may not be handled properly',
213
+ recommendation: 'Ensure errors are properly handled (thrown, returned, or displayed to users)'
214
+ });
215
+ }
216
+ }
217
+
218
+ // Check for missing error states in components using pace-core hooks
219
+ // Only check React component files
220
+ if (filePath.match(/\.(tsx|jsx)$/)) {
221
+ const paceCoreHooks = ['useUnifiedAuth', 'useOrganisations', 'useEvents', 'useSecureSupabase'];
222
+ paceCoreHooks.forEach(hookName => {
223
+ if (content.includes(hookName)) {
224
+ const hookPattern = new RegExp(`const\\s+[^=]+=\\s+${hookName}\\s*\\(`, 'g');
225
+ let hookMatch;
226
+ while ((hookMatch = hookPattern.exec(content)) !== null) {
227
+ // Check the entire component, not just 500 chars after hook
228
+ // React's Rules of Hooks require all hooks to be called before conditional returns,
229
+ // so error handling may occur later in the component
230
+ const hookLine = getLineNumber(content, hookMatch.index);
231
+ const lines = content.split('\n');
232
+ const hookLineIndex = hookLine - 1;
233
+
234
+ // Get the rest of the component after this hook
235
+ const afterHookContent = lines.slice(hookLineIndex).join('\n');
236
+
237
+ // Check if error is destructured from the hook
238
+ const hookCallLine = lines[hookLineIndex];
239
+ const hasErrorDestructured = /(error|Error|authError|orgError)/.test(hookCallLine);
240
+
241
+ // For useSecureSupabase, check for null checks (it returns null on error)
242
+ const isSecureSupabase = hookName === 'useSecureSupabase';
243
+ const hasNullCheck = isSecureSupabase && /secureSupabase\s*===?\s*null|!secureSupabase/.test(afterHookContent);
244
+
245
+ // Check for error handling patterns in the entire component:
246
+ // 1. Component-level error checks with early returns: if (error) return <ErrorUI />
247
+ // 2. useEffect error handlers: useEffect(() => { if (error) ... }, [error])
248
+ // 3. Null checks for useSecureSupabase: if (secureSupabase === null) ...
249
+ // 4. Error passed to error handling utilities
250
+
251
+ const hasComponentLevelErrorCheck = /if\s*\(\s*(error|authError|orgError|rbacError)/.test(afterHookContent);
252
+ const hasUseEffectErrorHandler = /useEffect\s*\([^)]*\([^)]*\)\s*=>\s*\{[^}]*\b(error|authError|orgError|rbacError)\b[^}]*\}/.test(afterHookContent);
253
+ const hasErrorInDeps = /useEffect\s*\([^)]*,\s*\[[^\]]*\b(error|authError|orgError|rbacError)\b/.test(afterHookContent);
254
+ const hasErrorHandling = /if\s*\(\s*(error|authError|orgError|rbacError)|(error|authError|orgError|rbacError)\s*\?|catch/.test(afterHookContent);
255
+ const hasErrorUtility = /handleSupabaseError|handleError|toast.*error|showError/.test(afterHookContent);
256
+
257
+ // Only flag if error is destructured but not handled anywhere
258
+ if (hasErrorDestructured && !hasComponentLevelErrorCheck && !hasUseEffectErrorHandler &&
259
+ !hasErrorInDeps && !hasErrorHandling && !hasErrorUtility && !hasNullCheck) {
260
+ warnings.push({
261
+ type: 'unhandled-hook-error',
262
+ file: relativePath,
263
+ line: hookLine,
264
+ message: `${hookName} may return an error that is not handled`,
265
+ recommendation: 'Check for error state and handle it appropriately. You can handle errors via: (1) Component-level checks after all hooks: if (error) return <ErrorUI />, (2) useEffect hooks that monitor error states, or (3) For useSecureSupabase, null checks: if (secureSupabase === null) ...'
266
+ });
267
+ }
268
+ }
269
+ }
270
+ });
271
+ }
272
+ } catch (error) {
273
+ // Skip files with errors
274
+ }
275
+ }
276
+
277
+ // Check if ErrorBoundary is used in main app file
278
+ // Skip this check if this is the pace-core repository (root src/ is a demo app)
279
+ if (!hasErrorBoundary && !isPaceCoreRepository) {
280
+ const mainFile = mainFiles.find(file => {
281
+ const filePath = path.join(projectRoot, 'src', file);
282
+ return fs.existsSync(filePath);
283
+ });
284
+
285
+ if (mainFile) {
286
+ suggestions.push({
287
+ type: 'missing-error-boundary',
288
+ file: `src/${mainFile}`,
289
+ message: 'No ErrorBoundary found in main app file',
290
+ recommendation: 'Wrap your app with ErrorBoundary from @jmruthers/pace-core to catch and handle React errors gracefully'
291
+ });
292
+ }
293
+ }
294
+
295
+ return { issues, warnings, suggestions };
296
+ }
297
+ };
298
+
299
+ module.exports = errorHandlingCheck;