@jmruthers/pace-core 0.6.1 → 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 (502) hide show
  1. package/CHANGELOG.md +43 -10
  2. package/cursor-rules/00-pace-core-compliance.mdc +18 -91
  3. package/cursor-rules/01-standards-compliance.mdc +16 -47
  4. package/cursor-rules/02-project-structure.mdc +4 -4
  5. package/cursor-rules/03-solid-principles.mdc +45 -164
  6. package/cursor-rules/04-testing-standards.mdc +22 -69
  7. package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
  8. package/cursor-rules/06-code-quality.mdc +42 -125
  9. package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
  10. package/cursor-rules/08-markup-quality.mdc +452 -0
  11. package/cursor-rules/CHANGELOG.md +18 -0
  12. package/cursor-rules/README.md +2 -1
  13. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
  14. package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
  15. package/dist/{DataTable-DQ7RSOHE.js → DataTable-TPTKCX4D.js} +10 -9
  16. package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +356 -111
  17. package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
  18. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
  19. package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
  20. package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
  21. package/dist/chunk-24UVZUZG.js.map +1 -0
  22. package/dist/{chunk-4N5C5XZU.js → chunk-2UOI2FG5.js} +4 -4
  23. package/dist/chunk-2UOI2FG5.js.map +1 -0
  24. package/dist/{chunk-T33XF5ZC.js → chunk-3XC4CPTD.js} +4317 -3963
  25. package/dist/chunk-3XC4CPTD.js.map +1 -0
  26. package/dist/{chunk-4ZC4GX36.js → chunk-6J4GEEJR.js} +172 -45
  27. package/dist/chunk-6J4GEEJR.js.map +1 -0
  28. package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
  29. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  30. package/dist/{chunk-BYFSK72L.js → chunk-EHMR7VYL.js} +4 -4
  31. package/dist/chunk-EHMR7VYL.js.map +1 -0
  32. package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
  33. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  34. package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
  35. package/dist/chunk-FFQEQTNW.js.map +1 -0
  36. package/dist/chunk-FMUCXFII.js +76 -0
  37. package/dist/chunk-FMUCXFII.js.map +1 -0
  38. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  39. package/dist/chunk-L4OXEN46.js.map +1 -0
  40. package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
  41. package/dist/chunk-M43Y4SSO.js.map +1 -0
  42. package/dist/{chunk-3XTALGJF.js → chunk-MMZ7JXPU.js} +60 -223
  43. package/dist/chunk-MMZ7JXPU.js.map +1 -0
  44. package/dist/{chunk-GLK6VM3F.js → chunk-NECFR5MM.js} +254 -170
  45. package/dist/chunk-NECFR5MM.js.map +1 -0
  46. package/dist/{chunk-JBKQ3SAO.js → chunk-SFZUDBL5.js} +40 -4
  47. package/dist/chunk-SFZUDBL5.js.map +1 -0
  48. package/dist/{chunk-XM25TVIE.js → chunk-XWQCNGTQ.js} +724 -363
  49. package/dist/chunk-XWQCNGTQ.js.map +1 -0
  50. package/dist/components.d.ts +5 -5
  51. package/dist/components.js +14 -11
  52. package/dist/components.js.map +1 -1
  53. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  54. package/dist/hooks.d.ts +55 -122
  55. package/dist/hooks.js +8 -12
  56. package/dist/hooks.js.map +1 -1
  57. package/dist/index.d.ts +60 -13
  58. package/dist/index.js +19 -19
  59. package/dist/index.js.map +1 -1
  60. package/dist/providers.d.ts +21 -3
  61. package/dist/providers.js +2 -2
  62. package/dist/rbac/index.d.ts +145 -114
  63. package/dist/rbac/index.js +8 -11
  64. package/dist/theming/runtime.d.ts +1 -13
  65. package/dist/theming/runtime.js +1 -1
  66. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  67. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  68. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  69. package/dist/types.d.ts +2 -2
  70. package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +31 -1
  71. package/dist/utils.d.ts +4 -5
  72. package/dist/utils.js +14 -14
  73. package/dist/utils.js.map +1 -1
  74. package/docs/api/README.md +7 -1
  75. package/docs/api/classes/ColumnFactory.md +8 -8
  76. package/docs/api/classes/InvalidScopeError.md +4 -4
  77. package/docs/api/classes/Logger.md +1 -1
  78. package/docs/api/classes/MissingUserContextError.md +4 -4
  79. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  80. package/docs/api/classes/PermissionDeniedError.md +4 -4
  81. package/docs/api/classes/RBACAuditManager.md +1 -1
  82. package/docs/api/classes/RBACCache.md +1 -1
  83. package/docs/api/classes/RBACEngine.md +1 -1
  84. package/docs/api/classes/RBACError.md +4 -4
  85. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  86. package/docs/api/classes/SecureSupabaseClient.md +18 -15
  87. package/docs/api/classes/StorageUtils.md +1 -1
  88. package/docs/api/enums/FileCategory.md +1 -1
  89. package/docs/api/enums/LogLevel.md +1 -1
  90. package/docs/api/enums/RBACErrorCode.md +1 -1
  91. package/docs/api/enums/RPCFunction.md +1 -1
  92. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  93. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  94. package/docs/api/interfaces/AggregateConfig.md +4 -4
  95. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  96. package/docs/api/interfaces/AvatarProps.md +1 -1
  97. package/docs/api/interfaces/BadgeProps.md +9 -2
  98. package/docs/api/interfaces/ButtonProps.md +7 -4
  99. package/docs/api/interfaces/CalendarProps.md +8 -5
  100. package/docs/api/interfaces/CardProps.md +8 -5
  101. package/docs/api/interfaces/ColorPalette.md +1 -1
  102. package/docs/api/interfaces/ColorShade.md +1 -1
  103. package/docs/api/interfaces/ComplianceResult.md +1 -1
  104. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  105. package/docs/api/interfaces/DataRecord.md +1 -1
  106. package/docs/api/interfaces/DataTableAction.md +24 -21
  107. package/docs/api/interfaces/DataTableColumn.md +31 -31
  108. package/docs/api/interfaces/DataTableProps.md +1 -1
  109. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  110. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  111. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  112. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  113. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  114. package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
  115. package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
  116. package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
  117. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  118. package/docs/api/interfaces/ExportColumn.md +1 -1
  119. package/docs/api/interfaces/ExportOptions.md +8 -8
  120. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  121. package/docs/api/interfaces/FileMetadata.md +1 -1
  122. package/docs/api/interfaces/FileReference.md +1 -1
  123. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  124. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  125. package/docs/api/interfaces/FileUploadProps.md +26 -23
  126. package/docs/api/interfaces/FooterProps.md +10 -8
  127. package/docs/api/interfaces/FormFieldProps.md +10 -10
  128. package/docs/api/interfaces/FormProps.md +1 -1
  129. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  130. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  131. package/docs/api/interfaces/InputProps.md +7 -4
  132. package/docs/api/interfaces/LabelProps.md +1 -1
  133. package/docs/api/interfaces/LoggerConfig.md +1 -1
  134. package/docs/api/interfaces/LoginFormProps.md +14 -11
  135. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  136. package/docs/api/interfaces/NavigationContextType.md +1 -1
  137. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  138. package/docs/api/interfaces/NavigationItem.md +11 -11
  139. package/docs/api/interfaces/NavigationMenuProps.md +15 -15
  140. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  141. package/docs/api/interfaces/Organisation.md +1 -1
  142. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  143. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  144. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  145. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  146. package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
  147. package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
  148. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  149. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  150. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  151. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  152. package/docs/api/interfaces/PaletteData.md +1 -1
  153. package/docs/api/interfaces/ParsedAddress.md +1 -1
  154. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  155. package/docs/api/interfaces/ProgressProps.md +1 -1
  156. package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
  157. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  158. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  159. package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
  160. package/docs/api/interfaces/QuickFix.md +1 -1
  161. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  162. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  163. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  164. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  165. package/docs/api/interfaces/RBACConfig.md +1 -1
  166. package/docs/api/interfaces/RBACContext.md +1 -1
  167. package/docs/api/interfaces/RBACLogger.md +1 -1
  168. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  169. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  170. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  171. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  172. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  173. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  174. package/docs/api/interfaces/RBACResult.md +1 -1
  175. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  176. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  177. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  178. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  179. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  180. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  181. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  182. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  183. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  184. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  185. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  186. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  187. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  188. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  189. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  190. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  191. package/docs/api/interfaces/RouteConfig.md +1 -1
  192. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  193. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  194. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  195. package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
  196. package/docs/api/interfaces/SetupIssue.md +1 -1
  197. package/docs/api/interfaces/StorageConfig.md +1 -1
  198. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  199. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  200. package/docs/api/interfaces/StorageListOptions.md +1 -1
  201. package/docs/api/interfaces/StorageListResult.md +1 -1
  202. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  203. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  204. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  205. package/docs/api/interfaces/StyleImport.md +1 -1
  206. package/docs/api/interfaces/SwitchProps.md +1 -1
  207. package/docs/api/interfaces/TabsContentProps.md +1 -1
  208. package/docs/api/interfaces/TabsListProps.md +1 -1
  209. package/docs/api/interfaces/TabsProps.md +1 -1
  210. package/docs/api/interfaces/TabsTriggerProps.md +3 -3
  211. package/docs/api/interfaces/TextareaProps.md +1 -1
  212. package/docs/api/interfaces/ToastActionElement.md +4 -1
  213. package/docs/api/interfaces/ToastProps.md +1 -1
  214. package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
  215. package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
  216. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  217. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  218. package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
  219. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  220. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  221. package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
  222. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  223. package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
  224. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  225. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
  226. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
  227. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  228. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  229. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  230. package/docs/api/interfaces/UserEventAccess.md +14 -11
  231. package/docs/api/interfaces/UserMenuProps.md +8 -6
  232. package/docs/api/interfaces/UserProfile.md +1 -1
  233. package/docs/api/modules.md +575 -634
  234. package/docs/architecture/database-schema-requirements.md +161 -0
  235. package/docs/core-concepts/rbac-system.md +3 -3
  236. package/docs/documentation-index.md +2 -4
  237. package/docs/getting-started/cursor-rules.md +2 -1
  238. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  239. package/docs/migration/MIGRATION_GUIDE.md +2 -24
  240. package/docs/migration/README.md +52 -6
  241. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  242. package/docs/migration/database-changes-december-2025.md +3 -3
  243. package/docs/rbac/event-based-apps.md +1 -1
  244. package/docs/rbac/getting-started.md +1 -1
  245. package/docs/rbac/quick-start.md +1 -1
  246. package/docs/standards/README.md +1 -0
  247. package/package.json +2 -1
  248. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  249. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  250. package/scripts/audit/core/checks/bundle.cjs +142 -0
  251. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +714 -687
  252. package/scripts/audit/core/checks/config.cjs +54 -0
  253. package/scripts/audit/core/checks/coverage.cjs +84 -0
  254. package/scripts/audit/core/checks/dependencies.cjs +454 -0
  255. package/scripts/audit/core/checks/documentation.cjs +203 -0
  256. package/scripts/audit/core/checks/environment.cjs +128 -0
  257. package/scripts/audit/core/checks/error-handling.cjs +299 -0
  258. package/scripts/audit/core/checks/forms.cjs +172 -0
  259. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  260. package/scripts/audit/core/checks/hooks.cjs +334 -0
  261. package/scripts/audit/core/checks/imports.cjs +244 -0
  262. package/scripts/audit/core/checks/performance.cjs +325 -0
  263. package/scripts/audit/core/checks/routes.cjs +117 -0
  264. package/scripts/audit/core/checks/state.cjs +130 -0
  265. package/scripts/audit/core/checks/structure.cjs +65 -0
  266. package/scripts/audit/core/checks/style.cjs +584 -0
  267. package/scripts/audit/core/checks/testing.cjs +122 -0
  268. package/scripts/audit/core/checks/typescript.cjs +61 -0
  269. package/scripts/audit/core/scanner.cjs +199 -0
  270. package/scripts/audit/core/utils.cjs +137 -0
  271. package/scripts/audit/index.cjs +223 -0
  272. package/scripts/audit/reporters/console.cjs +151 -0
  273. package/scripts/audit/reporters/json.cjs +54 -0
  274. package/scripts/audit/reporters/markdown.cjs +124 -0
  275. package/scripts/audit-consuming-app.cjs +61 -936
  276. package/scripts/build-docs/build-decision.js +240 -0
  277. package/scripts/build-docs/cache-utils.js +105 -0
  278. package/scripts/build-docs/content-normalization.js +150 -0
  279. package/scripts/build-docs/file-utils.js +105 -0
  280. package/scripts/build-docs/git-utils.js +86 -0
  281. package/scripts/build-docs/hash-utils.js +116 -0
  282. package/scripts/build-docs/typedoc-runner.js +220 -0
  283. package/scripts/build-docs-incremental.js +77 -913
  284. package/scripts/utils/command-runner.js +16 -11
  285. package/scripts/validate-formats.js +61 -56
  286. package/scripts/validate-master.js +74 -69
  287. package/scripts/validate-pre-publish.js +70 -65
  288. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  289. package/src/components/Alert/Alert.test.tsx +12 -18
  290. package/src/components/Alert/Alert.tsx +5 -7
  291. package/src/components/Avatar/Avatar.test.tsx +4 -4
  292. package/src/components/Badge/Badge.tsx +14 -0
  293. package/src/components/Button/Button.tsx +22 -0
  294. package/src/components/Calendar/Calendar.tsx +8 -2
  295. package/src/components/Card/Card.tsx +4 -0
  296. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  297. package/src/components/Checkbox/Checkbox.tsx +2 -2
  298. package/src/components/DataTable/DataTable.tsx +38 -4
  299. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  300. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
  301. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  302. package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
  303. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  304. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  305. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  306. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  307. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  308. package/src/components/DataTable/components/DataTableCore.tsx +196 -554
  309. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  310. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  311. package/src/components/DataTable/components/DataTableModals.tsx +8 -0
  312. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  313. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  314. package/src/components/DataTable/components/EditFields.tsx +307 -0
  315. package/src/components/DataTable/components/EditableRow.tsx +8 -0
  316. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  317. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  318. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  319. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  320. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  321. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  322. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  323. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  324. package/src/components/DataTable/components/UnifiedTableBody.tsx +61 -849
  325. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  326. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  327. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  328. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  329. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  330. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  331. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  332. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  333. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  334. package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
  335. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  336. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  337. package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
  338. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  339. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  340. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  341. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  342. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  343. package/src/components/DataTable/styles.ts +6 -6
  344. package/src/components/DataTable/types.ts +6 -10
  345. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  346. package/src/components/DataTable/utils/debugTools.ts +18 -113
  347. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  348. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  349. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  350. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  351. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  352. package/src/components/Dialog/Dialog.tsx +2 -2
  353. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  354. package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
  355. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  356. package/src/components/ErrorBoundary/index.ts +27 -2
  357. package/src/components/EventSelector/EventSelector.tsx +3 -0
  358. package/src/components/FileDisplay/FileDisplay.tsx +32 -18
  359. package/src/components/FileUpload/FileUpload.tsx +22 -2
  360. package/src/components/Footer/Footer.test.tsx +16 -16
  361. package/src/components/Footer/Footer.tsx +14 -11
  362. package/src/components/Form/Form.tsx +1 -0
  363. package/src/components/Header/Header.tsx +21 -10
  364. package/src/components/Input/Input.test.tsx +2 -2
  365. package/src/components/Input/Input.tsx +8 -4
  366. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  367. package/src/components/LoginForm/LoginForm.tsx +4 -0
  368. package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
  369. package/src/components/NavigationMenu/types.ts +56 -0
  370. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  371. package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
  372. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -2
  373. package/src/components/PaceAppLayout/PaceAppLayout.tsx +32 -11
  374. package/src/components/PaceAppLayout/test-setup.tsx +1 -2
  375. package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
  376. package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
  377. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  378. package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
  379. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  380. package/src/components/Select/Select.tsx +80 -434
  381. package/src/components/Select/context.ts +23 -0
  382. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  383. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  384. package/src/components/Select/hooks/useSelectState.ts +104 -0
  385. package/src/components/Select/index.ts +9 -1
  386. package/src/components/Select/types.ts +123 -0
  387. package/src/components/Select/utils/text.ts +26 -0
  388. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
  389. package/src/components/Switch/Switch.tsx +4 -4
  390. package/src/components/Tabs/Tabs.tsx +1 -1
  391. package/src/components/Toast/Toast.tsx +4 -0
  392. package/src/components/Tooltip/Tooltip.tsx +2 -2
  393. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  394. package/src/components/UserMenu/UserMenu.tsx +21 -18
  395. package/src/components/index.ts +2 -2
  396. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  397. package/src/hooks/index.ts +1 -2
  398. package/src/hooks/public/usePublicEvent.ts +4 -0
  399. package/src/hooks/public/usePublicEventLogo.ts +4 -0
  400. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  401. package/src/hooks/public/usePublicRouteParams.ts +4 -0
  402. package/src/hooks/services/useAuth.ts +32 -0
  403. package/src/hooks/services/useCurrentEvent.ts +6 -0
  404. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  405. package/src/hooks/useDebounce.ts +9 -0
  406. package/src/hooks/useEventTheme.ts +6 -0
  407. package/src/hooks/useFileDisplay.ts +4 -0
  408. package/src/hooks/useFileReference.ts +25 -7
  409. package/src/hooks/useFileUrl.ts +11 -1
  410. package/src/hooks/useFocusManagement.ts +14 -0
  411. package/src/hooks/useFocusTrap.ts +3 -0
  412. package/src/hooks/useInactivityTracker.ts +3 -0
  413. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  414. package/src/hooks/useOrganisationPermissions.ts +4 -0
  415. package/src/hooks/useOrganisationSecurity.ts +4 -0
  416. package/src/hooks/usePerformanceMonitor.ts +4 -0
  417. package/src/hooks/usePermissionCache.ts +7 -0
  418. package/src/hooks/useQueryCache.ts +12 -1
  419. package/src/hooks/useSessionRestoration.ts +4 -0
  420. package/src/hooks/useStorage.ts +4 -0
  421. package/src/hooks/useToast.ts +1 -1
  422. package/src/index.ts +2 -1
  423. package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
  424. package/src/providers/services/AuthServiceProvider.tsx +18 -0
  425. package/src/providers/services/EventServiceProvider.tsx +18 -0
  426. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  427. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  428. package/src/providers/services/UnifiedAuthProvider.tsx +36 -0
  429. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
  430. package/src/rbac/README.md +1 -1
  431. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +2 -2
  432. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  433. package/src/rbac/adapters.tsx +14 -5
  434. package/src/rbac/api.ts +100 -67
  435. package/src/rbac/components/NavigationProvider.tsx +4 -1
  436. package/src/rbac/components/PagePermissionGuard.tsx +157 -17
  437. package/src/rbac/components/RoleBasedRouter.tsx +5 -1
  438. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  439. package/src/rbac/components/SecureDataProvider.tsx +20 -5
  440. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  441. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  442. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  443. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  444. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  445. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  446. package/src/rbac/engine.ts +38 -14
  447. package/src/rbac/hooks/permissions/index.ts +7 -0
  448. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  449. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  450. package/src/rbac/hooks/permissions/useCan.ts +347 -0
  451. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  452. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  453. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  454. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  455. package/src/rbac/hooks/useCan.test.ts +71 -64
  456. package/src/rbac/hooks/usePermissions.ts +14 -995
  457. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  458. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  459. package/src/rbac/hooks/useSecureSupabase.ts +33 -13
  460. package/src/rbac/permissions.ts +0 -30
  461. package/src/rbac/secureClient.ts +200 -61
  462. package/src/rbac/types.ts +8 -0
  463. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  464. package/src/theming/parseEventColours.ts +5 -19
  465. package/src/types/vitest-globals.d.ts +51 -26
  466. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  467. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  468. package/src/utils/__tests__/index.unit.test.ts +2 -2
  469. package/src/utils/audit/audit.ts +0 -3
  470. package/src/utils/core/cn.ts +1 -1
  471. package/src/utils/file-reference/index.ts +53 -1
  472. package/src/utils/formatting/formatting.ts +8 -18
  473. package/src/utils/index.ts +0 -1
  474. package/dist/chunk-3QRJFVBR.js.map +0 -1
  475. package/dist/chunk-3XTALGJF.js.map +0 -1
  476. package/dist/chunk-4N5C5XZU.js.map +0 -1
  477. package/dist/chunk-4ZC4GX36.js.map +0 -1
  478. package/dist/chunk-BYFSK72L.js.map +0 -1
  479. package/dist/chunk-EXUD6RNJ.js +0 -451
  480. package/dist/chunk-EXUD6RNJ.js.map +0 -1
  481. package/dist/chunk-GLK6VM3F.js.map +0 -1
  482. package/dist/chunk-I7PSE6JW.js.map +0 -1
  483. package/dist/chunk-JBKQ3SAO.js.map +0 -1
  484. package/dist/chunk-KNC55RTG.js.map +0 -1
  485. package/dist/chunk-LXQLPRQ2.js.map +0 -1
  486. package/dist/chunk-R77UEZ4E.js.map +0 -1
  487. package/dist/chunk-SQGMNID3.js.map +0 -1
  488. package/dist/chunk-T33XF5ZC.js.map +0 -1
  489. package/dist/chunk-XM25TVIE.js.map +0 -1
  490. package/docs/api/classes/ErrorBoundary.md +0 -144
  491. package/docs/migration/quick-migration-guide.md +0 -356
  492. package/docs/migration/service-architecture.md +0 -281
  493. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  494. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  495. package/src/hooks/useSecureDataAccess.ts +0 -681
  496. /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-TPTKCX4D.js.map} +0 -0
  497. /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
  498. /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
  499. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  500. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  501. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  502. /package/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
@@ -1,961 +1,86 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Comprehensive Audit Tool for Consuming Apps
4
+ * Audit Script for Consuming Apps
5
5
  * @package @jmruthers/pace-core
6
- * @module Scripts/audit-consuming-app
7
6
  *
8
- * Performs comprehensive audit of consuming app including:
9
- * - Phase 1: Deterministic checks (file structure, configs, coverage)
10
- * - Phase 2: Heuristic checks (SOLID principles, code complexity)
11
- * - Standards compliance
12
- * - Testing compliance
13
- * - Code quality metrics
14
- *
15
- * Generates timestamped markdown report in audit/ directory.
7
+ * This script allows consuming apps to run pace-core audits.
8
+ * It resolves the audit script path relative to the installed pace-core package
9
+ * and forwards all arguments to the main audit script.
16
10
  */
17
11
 
18
- const fs = require('fs');
19
12
  const path = require('path');
13
+ const fs = require('fs');
14
+ const { spawn } = require('child_process');
20
15
 
21
- // Import existing compliance checker
22
- let complianceChecker;
23
- try {
24
- complianceChecker = require('./check-pace-core-compliance.cjs');
25
- } catch (error) {
26
- console.error('Error loading compliance checker:', error.message);
27
- process.exit(1);
28
- }
29
-
30
- // Run compliance check and get results
31
- function runComplianceCheck(projectRoot) {
32
- const manifest = complianceChecker.loadManifest();
33
- const files = complianceChecker.findSourceFiles(projectRoot, []);
34
-
35
- console.log(` Scanning ${files.length} files for compliance issues...`);
36
-
37
- // Scan all files
38
- const allViolations = {
39
- restrictedImports: [],
40
- duplicateComponents: [],
41
- duplicateHooks: [],
42
- duplicateUtils: [],
43
- suggestions: [],
44
- customAuthCode: [],
45
- duplicateConfig: [],
46
- unprotectedPages: [],
47
- directSupabaseAuth: [],
48
- providerSetupIssues: [],
49
- viteConfigIssues: [],
50
- routerSetupIssues: [],
51
- unnecessaryWrappers: [],
52
- appDiscoveryIssues: []
53
- };
54
-
55
- let scanned = 0;
56
- files.forEach(file => {
57
- try {
58
- const violations = complianceChecker.scanFile(file, manifest);
59
- allViolations.restrictedImports.push(...violations.restrictedImports);
60
- allViolations.duplicateComponents.push(...violations.duplicateComponents);
61
- allViolations.duplicateHooks.push(...violations.duplicateHooks);
62
- allViolations.duplicateUtils.push(...violations.duplicateUtils);
63
- allViolations.suggestions.push(...violations.suggestions);
64
- allViolations.customAuthCode.push(...violations.customAuthCode);
65
- allViolations.duplicateConfig.push(...violations.duplicateConfig);
66
- allViolations.unprotectedPages.push(...violations.unprotectedPages);
67
- allViolations.directSupabaseAuth.push(...violations.directSupabaseAuth);
68
- allViolations.providerSetupIssues.push(...violations.providerSetupIssues);
69
- allViolations.viteConfigIssues.push(...violations.viteConfigIssues);
70
- allViolations.routerSetupIssues.push(...violations.routerSetupIssues);
71
- allViolations.unnecessaryWrappers.push(...violations.unnecessaryWrappers);
72
- allViolations.appDiscoveryIssues.push(...violations.appDiscoveryIssues);
73
- scanned++;
74
- if (scanned % 50 === 0) {
75
- process.stdout.write(` Scanned ${scanned}/${files.length} files...\r`);
76
- }
77
- } catch (error) {
78
- // Skip files with errors
79
- scanned++;
80
- }
81
- });
82
-
83
- if (scanned > 0) {
84
- process.stdout.write(` Scanned ${scanned}/${files.length} files...\n`);
85
- }
86
-
87
- return allViolations;
88
- }
89
-
90
- // Convert compliance violations to markdown
91
- function complianceViolationsToMarkdown(allViolations) {
92
- let markdown = '';
93
-
94
- const totalRestricted = allViolations.restrictedImports.length;
95
- const totalDuplicates =
96
- allViolations.duplicateComponents.length +
97
- allViolations.duplicateHooks.length +
98
- allViolations.duplicateUtils.length;
99
- const totalSuggestions = allViolations.suggestions.length;
100
- const totalRbacAuth =
101
- allViolations.customAuthCode.length +
102
- allViolations.duplicateConfig.length +
103
- allViolations.unprotectedPages.length +
104
- allViolations.directSupabaseAuth.length;
105
- const totalSetupIssues =
106
- allViolations.providerSetupIssues.length +
107
- allViolations.viteConfigIssues.length +
108
- allViolations.routerSetupIssues.length;
109
- const totalUnnecessaryWrappers = allViolations.unnecessaryWrappers.length;
110
- const totalAppDiscovery = allViolations.appDiscoveryIssues.length;
111
- const totalIssues = totalRestricted + totalDuplicates + totalSuggestions + totalRbacAuth + totalSetupIssues + totalUnnecessaryWrappers + totalAppDiscovery;
112
-
113
- markdown += `### Summary\n\n`;
114
- markdown += `- **Total Issues:** ${totalIssues}\n`;
115
- markdown += `- **Restricted Imports:** ${totalRestricted}\n`;
116
- markdown += `- **Duplicate Components/Hooks/Utils:** ${totalDuplicates}\n`;
117
- markdown += `- **RBAC/Auth Issues:** ${totalRbacAuth}\n`;
118
- markdown += `- **Setup Issues:** ${totalSetupIssues}\n`;
119
- markdown += `- **Unnecessary Wrappers:** ${totalUnnecessaryWrappers}\n`;
120
- markdown += `- **App Discovery Issues:** ${totalAppDiscovery}\n`;
121
- markdown += `- **Suggestions:** ${totalSuggestions}\n\n`;
122
-
123
- // Restricted Imports
124
- if (totalRestricted > 0) {
125
- markdown += `#### ❌ Restricted Imports (${totalRestricted})\n\n`;
126
- allViolations.restrictedImports.forEach(({ module, reason, file, line }) => {
127
- markdown += `- **${file}:${line}**\n`;
128
- markdown += ` - Import: \`${module}\`\n`;
129
- markdown += ` - Reason: ${reason}\n\n`;
130
- });
131
- } else {
132
- markdown += `#### ✅ No Restricted Imports\n\n`;
133
- }
134
-
135
- // Duplicate Components
136
- if (allViolations.duplicateComponents.length > 0) {
137
- markdown += `#### ❌ Duplicate Components (${allViolations.duplicateComponents.length})\n\n`;
138
- allViolations.duplicateComponents.forEach(({ component, file }) => {
139
- markdown += `- **${file}**\n`;
140
- markdown += ` - Component \`${component}\` conflicts with pace-core component\n`;
141
- markdown += ` - Suggestion: Use \`${component}\` from '@jmruthers/pace-core' instead\n\n`;
142
- });
143
- }
144
-
145
- // Duplicate Hooks
146
- if (allViolations.duplicateHooks.length > 0) {
147
- markdown += `#### ❌ Duplicate Hooks (${allViolations.duplicateHooks.length})\n\n`;
148
- allViolations.duplicateHooks.forEach(({ hook, file }) => {
149
- markdown += `- **${file}**\n`;
150
- markdown += ` - Hook \`${hook}\` conflicts with pace-core hook\n`;
151
- markdown += ` - Suggestion: Use \`${hook}\` from '@jmruthers/pace-core' instead\n\n`;
152
- });
153
- }
154
-
155
- // Duplicate Utils
156
- if (allViolations.duplicateUtils.length > 0) {
157
- markdown += `#### ❌ Duplicate Utils (${allViolations.duplicateUtils.length})\n\n`;
158
- allViolations.duplicateUtils.forEach(({ util, file }) => {
159
- markdown += `- **${file}**\n`;
160
- markdown += ` - Util \`${util}\` conflicts with pace-core util\n`;
161
- markdown += ` - Suggestion: Use \`${util}\` from '@jmruthers/pace-core' instead\n\n`;
162
- });
163
- }
164
-
165
- // Unnecessary Wrappers
166
- if (totalUnnecessaryWrappers > 0) {
167
- markdown += `#### ⚠️ Unnecessary Wrappers (${totalUnnecessaryWrappers})\n\n`;
168
- allViolations.unnecessaryWrappers.forEach(({ component, wrappedComponent, file, line, reason, recommendation }) => {
169
- markdown += `- **${file}:${line}**\n`;
170
- markdown += ` - Component: \`${component}\`\n`;
171
- markdown += ` - Wraps: \`${wrappedComponent}\`\n`;
172
- markdown += ` - Issue: ${reason}\n`;
173
- if (recommendation) {
174
- markdown += ` - Recommendation: ${recommendation}\n\n`;
175
- } else {
176
- markdown += ` - Recommendation: Remove the wrapper and use the component directly.\n\n`;
177
- }
178
- });
179
- }
180
-
181
- // Custom Auth/RBAC Code
182
- if (allViolations.customAuthCode.length > 0) {
183
- // Separate by severity
184
- const errors = allViolations.customAuthCode.filter(v => !v.severity || v.severity === 'error');
185
- const warnings = allViolations.customAuthCode.filter(v => v.severity === 'warning');
186
-
187
- if (errors.length > 0) {
188
- markdown += `#### ❌ Custom Auth/RBAC Code (${errors.length})\n\n`;
189
- errors.forEach(({ name, type, file, line, reason, replacement, example }) => {
190
- markdown += `- **${file}:${line}**\n`;
191
- markdown += ` - ${type}: \`${name}\`\n`;
192
- markdown += ` - Reason: ${reason}\n`;
193
- if (replacement) {
194
- markdown += ` - Fix: ${replacement}\n`;
195
- }
196
- if (example) {
197
- markdown += ` - Example:\n\`\`\`typescript\n${example}\n\`\`\`\n`;
198
- }
199
- markdown += `\n`;
200
- });
201
- }
202
-
203
- if (warnings.length > 0) {
204
- markdown += `#### ⚠️ Custom Auth/RBAC Warnings (${warnings.length})\n\n`;
205
- warnings.forEach(({ name, type, file, line, reason, replacement, example }) => {
206
- markdown += `- **${file}:${line}**\n`;
207
- markdown += ` - ${type}: \`${name}\`\n`;
208
- markdown += ` - Note: ${reason}\n`;
209
- if (replacement) {
210
- markdown += ` - Recommendation: ${replacement}\n`;
211
- }
212
- if (example) {
213
- markdown += ` - Example:\n\`\`\`typescript\n${example}\n\`\`\`\n`;
214
- }
215
- markdown += `\n`;
216
- });
217
- }
218
- }
219
-
220
- // Duplicate Configurations
221
- if (allViolations.duplicateConfig.length > 0) {
222
- markdown += `#### ❌ Duplicate Configurations (${allViolations.duplicateConfig.length})\n\n`;
223
- allViolations.duplicateConfig.forEach(({ type, file, count, reason }) => {
224
- markdown += `- **${file}**\n`;
225
- markdown += ` - Type: \`${type}\`${count ? ` (${count} instances)` : ''}\n`;
226
- markdown += ` - Reason: ${reason}\n\n`;
227
- });
228
- }
229
-
230
- // Provider Setup Issues
231
- if (allViolations.providerSetupIssues.length > 0) {
232
- markdown += `#### ❌ Provider Setup Issues (${allViolations.providerSetupIssues.length})\n\n`;
233
- allViolations.providerSetupIssues.forEach(({ issue, file, line, recommendation }) => {
234
- markdown += `- **${file}:${line}**\n`;
235
- markdown += ` - Issue: ${issue}\n`;
236
- if (recommendation) {
237
- markdown += ` - Recommendation: ${recommendation}\n\n`;
238
- }
239
- });
240
- }
241
-
242
- // Vite Config Issues
243
- if (allViolations.viteConfigIssues.length > 0) {
244
- markdown += `#### ❌ Vite Config Issues (${allViolations.viteConfigIssues.length})\n\n`;
245
- allViolations.viteConfigIssues.forEach(({ issue, file, line, recommendation }) => {
246
- markdown += `- **${file}:${line}**\n`;
247
- markdown += ` - Issue: ${issue}\n`;
248
- if (recommendation) {
249
- markdown += ` - Recommendation: ${recommendation}\n\n`;
250
- }
251
- });
252
- }
253
-
254
- // Router Setup Issues
255
- if (allViolations.routerSetupIssues.length > 0) {
256
- markdown += `#### ❌ Router Setup Issues (${allViolations.routerSetupIssues.length})\n\n`;
257
- allViolations.routerSetupIssues.forEach(({ issue, file, line, recommendation }) => {
258
- markdown += `- **${file}:${line}**\n`;
259
- markdown += ` - Issue: ${issue}\n`;
260
- if (recommendation) {
261
- markdown += ` - Recommendation: ${recommendation}\n\n`;
262
- }
263
- });
264
- }
265
-
266
- // Unprotected Pages
267
- if (allViolations.unprotectedPages.length > 0) {
268
- markdown += `#### ❌ Unprotected Pages (${allViolations.unprotectedPages.length})\n\n`;
269
- allViolations.unprotectedPages.forEach(({ page, file, recommendation }) => {
270
- markdown += `- **${file}**\n`;
271
- markdown += ` - Page: ${page}\n`;
272
- if (recommendation) {
273
- markdown += ` - Recommendation: ${recommendation}\n\n`;
274
- }
275
- });
276
- }
277
-
278
- // Direct Supabase Auth
279
- if (allViolations.directSupabaseAuth.length > 0) {
280
- markdown += `#### ❌ Direct Supabase Auth Usage (${allViolations.directSupabaseAuth.length})\n\n`;
281
- allViolations.directSupabaseAuth.forEach(({ file, line, recommendation }) => {
282
- markdown += `- **${file}:${line}**\n`;
283
- if (recommendation) {
284
- markdown += ` - Recommendation: ${recommendation}\n\n`;
285
- }
286
- });
287
- }
288
-
289
- // App Discovery Issues
290
- if (totalAppDiscovery > 0) {
291
- markdown += `#### ⚠️ App Discovery Issues (${totalAppDiscovery})\n\n`;
292
- allViolations.appDiscoveryIssues.forEach(({ issue, file, recommendation }) => {
293
- markdown += `- **${file}**\n`;
294
- markdown += ` - Issue: ${issue}\n`;
295
- if (recommendation) {
296
- markdown += ` - Recommendation: ${recommendation}\n\n`;
297
- }
298
- });
299
- }
300
-
301
- // Suggestions
302
- if (totalSuggestions > 0) {
303
- markdown += `#### 💡 Suggestions (${totalSuggestions})\n\n`;
304
- const grouped = {};
305
- allViolations.suggestions.forEach(s => {
306
- if (!grouped[s.file]) grouped[s.file] = [];
307
- grouped[s.file].push(s);
308
- });
309
- Object.entries(grouped).forEach(([file, suggestions]) => {
310
- markdown += `- **${file}**\n`;
311
- suggestions.forEach(s => {
312
- markdown += ` - ${s.suggestion}\n`;
313
- });
314
- markdown += `\n`;
315
- });
316
- }
317
-
318
- if (totalIssues === 0) {
319
- markdown += `✅ **Excellent!** No compliance issues found.\n\n`;
320
- }
321
-
322
- return markdown;
323
- }
324
-
325
- // ANSI color codes
326
- const colors = {
327
- reset: '\x1b[0m',
328
- green: '\x1b[32m',
329
- yellow: '\x1b[33m',
330
- blue: '\x1b[34m',
331
- cyan: '\x1b[36m',
332
- bold: '\x1b[1m',
333
- red: '\x1b[31m'
334
- };
16
+ // Find the pace-core package directory and audit script
17
+ // This script should be at: node_modules/@jmruthers/pace-core/scripts/audit-consuming-app.cjs
18
+ // The audit script should be at: node_modules/@jmruthers/pace-core/scripts/audit/index.cjs
335
19
 
336
- // Find project root
337
- function findProjectRoot() {
338
- let current = path.resolve(process.cwd());
339
- while (current !== path.dirname(current)) {
340
- if (fs.existsSync(path.join(current, 'package.json'))) {
341
- return current;
342
- }
343
- current = path.dirname(current);
344
- }
345
- return process.cwd();
346
- }
20
+ const scriptDir = __dirname;
21
+ let auditScript;
347
22
 
348
- // Get package.json info
349
- function getPackageInfo(projectRoot) {
350
- const packagePath = path.join(projectRoot, 'package.json');
351
- if (!fs.existsSync(packagePath)) {
352
- return null;
353
- }
23
+ // Strategy 1: If this script is in scripts/, the audit script is in scripts/audit/
24
+ const relativePath = path.join(scriptDir, 'audit', 'index.cjs');
25
+ if (fs.existsSync(relativePath)) {
26
+ auditScript = relativePath;
27
+ } else {
28
+ // Strategy 2: Try to resolve via package.json location
354
29
  try {
355
- return JSON.parse(fs.readFileSync(packagePath, 'utf8'));
356
- } catch (error) {
357
- return null;
358
- }
359
- }
360
-
361
- // Get pace-core version
362
- function getPaceCoreVersion(packageJson) {
363
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
364
- return deps['@jmruthers/pace-core'] || 'unknown';
365
- }
366
-
367
- // Phase 1: Deterministic Checks
368
-
369
- // Check file structure
370
- function checkFileStructure(projectRoot) {
371
- const issues = [];
372
- const warnings = [];
373
-
374
- const requiredDirs = ['src'];
375
- const recommendedDirs = ['src/components', 'src/hooks', 'src/utils', 'src/pages'];
376
-
377
- requiredDirs.forEach(dir => {
378
- const dirPath = path.join(projectRoot, dir);
379
- if (!fs.existsSync(dirPath)) {
380
- issues.push({
381
- type: 'missing-directory',
382
- directory: dir,
383
- severity: 'error',
384
- message: `Required directory '${dir}' is missing`
385
- });
386
- }
387
- });
388
-
389
- recommendedDirs.forEach(dir => {
390
- const dirPath = path.join(projectRoot, dir);
391
- if (!fs.existsSync(dirPath)) {
392
- warnings.push({
393
- type: 'missing-directory',
394
- directory: dir,
395
- severity: 'warning',
396
- message: `Recommended directory '${dir}' is missing`
397
- });
30
+ const packageJsonPath = require.resolve('@jmruthers/pace-core/package.json');
31
+ const packageDir = path.dirname(packageJsonPath);
32
+ const resolvedPath = path.join(packageDir, 'scripts', 'audit', 'index.cjs');
33
+ if (fs.existsSync(resolvedPath)) {
34
+ auditScript = resolvedPath;
398
35
  }
399
- });
400
-
401
- return { issues, warnings };
402
- }
403
-
404
- // Check config files
405
- function checkConfigFiles(projectRoot) {
406
- const issues = [];
407
- const warnings = [];
408
-
409
- const requiredConfigs = [
410
- { file: 'package.json', severity: 'error' },
411
- { file: 'tsconfig.json', severity: 'error' },
412
- { file: 'vite.config.ts', severity: 'warning' },
413
- { file: 'vitest.config.ts', severity: 'warning' }
414
- ];
415
-
416
- requiredConfigs.forEach(({ file, severity }) => {
417
- const filePath = path.join(projectRoot, file);
418
- if (!fs.existsSync(filePath)) {
419
- if (severity === 'error') {
420
- issues.push({
421
- type: 'missing-config',
422
- file,
423
- severity,
424
- message: `Required config file '${file}' is missing`
425
- });
426
- } else {
427
- warnings.push({
428
- type: 'missing-config',
429
- file,
430
- severity,
431
- message: `Recommended config file '${file}' is missing`
432
- });
433
- }
434
- }
435
- });
436
-
437
- return { issues, warnings };
438
- }
439
-
440
- // Check TypeScript strict mode
441
- function checkTypeScriptConfig(projectRoot) {
442
- const issues = [];
443
- const warnings = [];
444
-
445
- const tsconfigPath = path.join(projectRoot, 'tsconfig.json');
446
- if (!fs.existsSync(tsconfigPath)) {
447
- return { issues, warnings };
36
+ } catch (e) {
37
+ // Package not found via require.resolve, continue to fallback
448
38
  }
449
39
 
450
- try {
451
- const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
452
- const compilerOptions = tsconfig.compilerOptions || {};
453
-
454
- if (!compilerOptions.strict) {
455
- issues.push({
456
- type: 'typescript-config',
457
- severity: 'error',
458
- message: 'TypeScript strict mode is not enabled',
459
- recommendation: 'Set "strict": true in tsconfig.json'
460
- });
40
+ // Strategy 3: Fallback - assume we're in scripts/ and go up one level
41
+ if (!auditScript) {
42
+ const paceCoreRoot = path.resolve(scriptDir, '..');
43
+ const fallbackPath = path.join(paceCoreRoot, 'scripts', 'audit', 'index.cjs');
44
+ if (fs.existsSync(fallbackPath)) {
45
+ auditScript = fallbackPath;
461
46
  }
462
-
463
- if (compilerOptions.noImplicitAny === false) {
464
- issues.push({
465
- type: 'typescript-config',
466
- severity: 'error',
467
- message: 'noImplicitAny is disabled',
468
- recommendation: 'Set "noImplicitAny": true in tsconfig.json'
469
- });
470
- }
471
- } catch (error) {
472
- warnings.push({
473
- type: 'typescript-config',
474
- severity: 'warning',
475
- message: `Could not parse tsconfig.json: ${error.message}`
476
- });
477
47
  }
478
-
479
- return { issues, warnings };
480
48
  }
481
49
 
482
- // Check test coverage
483
- function checkTestCoverage(projectRoot) {
484
- const issues = [];
485
- const warnings = [];
486
-
487
- // Try to find coverage report
488
- const coveragePaths = [
489
- path.join(projectRoot, 'coverage', 'coverage-summary.json'),
490
- path.join(projectRoot, 'coverage', 'coverage-final.json')
491
- ];
492
-
493
- let coverageData = null;
494
- for (const coveragePath of coveragePaths) {
495
- if (fs.existsSync(coveragePath)) {
496
- try {
497
- coverageData = JSON.parse(fs.readFileSync(coveragePath, 'utf8'));
498
- break;
499
- } catch (error) {
500
- // Continue to next path
501
- }
502
- }
503
- }
504
-
505
- if (!coverageData) {
506
- warnings.push({
507
- type: 'coverage',
508
- severity: 'warning',
509
- message: 'No coverage report found. Run tests with coverage to get accurate metrics.'
510
- });
511
- return { issues, warnings };
512
- }
513
-
514
- // Check coverage thresholds
515
- const total = coverageData.total || {};
516
- const lines = total.lines?.pct || 0;
517
- const functions = total.functions?.pct || 0;
518
- const branches = total.branches?.pct || 0;
519
- const statements = total.statements?.pct || 0;
520
-
521
- if (lines < 70) {
522
- warnings.push({
523
- type: 'coverage',
524
- severity: 'warning',
525
- message: `Line coverage is ${lines.toFixed(1)}%, below recommended 70%`
526
- });
527
- }
528
-
529
- if (functions < 70) {
530
- warnings.push({
531
- type: 'coverage',
532
- severity: 'warning',
533
- message: `Function coverage is ${functions.toFixed(1)}%, below recommended 70%`
534
- });
535
- }
536
-
537
- return { issues, warnings, metrics: { lines, functions, branches, statements } };
50
+ // Verify the audit script exists
51
+ if (!auditScript || !fs.existsSync(auditScript)) {
52
+ console.error(`Error: Audit script not found.`);
53
+ console.error(`Searched locations:`);
54
+ console.error(` - ${path.join(scriptDir, 'audit', 'index.cjs')}`);
55
+ try {
56
+ const packageJsonPath = require.resolve('@jmruthers/pace-core/package.json');
57
+ const packageDir = path.dirname(packageJsonPath);
58
+ console.error(` - ${path.join(packageDir, 'scripts', 'audit', 'index.cjs')}`);
59
+ } catch (e) {
60
+ console.error(` - (Could not resolve package location)`);
61
+ }
62
+ console.error(`\nThis may indicate:`);
63
+ console.error(` 1. The pace-core package is not installed correctly`);
64
+ console.error(` 2. The package needs to be updated (npm install @jmruthers/pace-core@latest)`);
65
+ console.error(` 3. The scripts directory was not included in the published package`);
66
+ process.exit(1);
538
67
  }
539
68
 
540
- // Phase 2: Heuristic Checks
69
+ // Forward all command line arguments to the audit script
70
+ const args = process.argv.slice(2);
541
71
 
542
- // Check for large files
543
- function checkLargeFiles(projectRoot) {
544
- const suggestions = [];
545
- const maxLines = 500;
546
-
547
- function scanDirectory(dir, relativePath = '') {
548
- const items = fs.readdirSync(dir);
549
-
550
- items.forEach(item => {
551
- const fullPath = path.join(dir, item);
552
- const stat = fs.statSync(fullPath);
553
-
554
- if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules' && item !== 'dist') {
555
- scanDirectory(fullPath, path.join(relativePath, item));
556
- } else if (stat.isFile() && /\.(ts|tsx|js|jsx)$/.test(item)) {
557
- const content = fs.readFileSync(fullPath, 'utf8');
558
- const lines = content.split('\n').length;
559
-
560
- if (lines > maxLines) {
561
- suggestions.push({
562
- type: 'large-file',
563
- file: path.join(relativePath, item),
564
- lines,
565
- severity: 'suggestion',
566
- message: `File has ${lines} lines, consider splitting into smaller modules`
567
- });
568
- }
569
- }
570
- });
571
- }
572
-
573
- const srcPath = path.join(projectRoot, 'src');
574
- if (fs.existsSync(srcPath)) {
575
- scanDirectory(srcPath, 'src');
576
- }
577
-
578
- return suggestions;
579
- }
580
-
581
- // Check for god objects (heuristic)
582
- function checkGodObjects(projectRoot) {
583
- const suggestions = [];
584
-
585
- // This is a simplified heuristic - in practice, you'd use AST parsing
586
- function scanFile(filePath, relativePath) {
587
- try {
588
- const content = fs.readFileSync(filePath, 'utf8');
589
-
590
- // Heuristic: Files with many exports might be god objects
591
- const exportCount = (content.match(/export\s+(const|function|class|interface|type)/g) || []).length;
592
-
593
- if (exportCount > 10) {
594
- suggestions.push({
595
- type: 'god-object',
596
- file: relativePath,
597
- exportCount,
598
- severity: 'suggestion',
599
- message: `File exports ${exportCount} items, consider splitting into smaller modules`
600
- });
601
- }
602
- } catch (error) {
603
- // Skip files we can't read
604
- }
605
- }
606
-
607
- function scanDirectory(dir, relativePath = '') {
608
- const items = fs.readdirSync(dir);
609
-
610
- items.forEach(item => {
611
- const fullPath = path.join(dir, item);
612
- const stat = fs.statSync(fullPath);
613
-
614
- if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules' && item !== 'dist') {
615
- scanDirectory(fullPath, path.join(relativePath, item));
616
- } else if (stat.isFile() && /\.(ts|tsx|js|jsx)$/.test(item)) {
617
- scanFile(fullPath, path.join(relativePath, item));
618
- }
619
- });
620
- }
621
-
622
- const srcPath = path.join(projectRoot, 'src');
623
- if (fs.existsSync(srcPath)) {
624
- scanDirectory(srcPath, 'src');
625
- }
626
-
627
- return suggestions;
628
- }
72
+ // Spawn the audit script with forwarded arguments
73
+ const child = spawn('node', [auditScript, ...args], {
74
+ stdio: 'inherit',
75
+ cwd: process.cwd() // Use the consuming app's working directory
76
+ });
629
77
 
630
- // Generate markdown report
631
- function generateMarkdownReport(auditResults, projectRoot, packageJson, paceCoreVersion) {
632
- const timestamp = new Date();
633
- // Format: yyyymmddhhmmss
634
- const year = timestamp.getFullYear();
635
- const month = String(timestamp.getMonth() + 1).padStart(2, '0');
636
- const day = String(timestamp.getDate()).padStart(2, '0');
637
- const hours = String(timestamp.getHours()).padStart(2, '0');
638
- const minutes = String(timestamp.getMinutes()).padStart(2, '0');
639
- const seconds = String(timestamp.getSeconds()).padStart(2, '0');
640
- const timestampStr = `${year}${month}${day}${hours}${minutes}${seconds}`;
641
- const filename = `audit-${timestampStr}.md`;
642
- const auditDir = path.join(projectRoot, 'audit');
643
-
644
- // Create audit directory if it doesn't exist
645
- if (!fs.existsSync(auditDir)) {
646
- fs.mkdirSync(auditDir, { recursive: true });
647
- }
648
-
649
- const reportPath = path.join(auditDir, filename);
650
-
651
- // Calculate totals
652
- const phase1Errors = auditResults.phase1.issues.length;
653
- const phase1Warnings = auditResults.phase1.warnings.length;
654
- const phase2Suggestions = auditResults.phase2.suggestions.length;
655
-
656
- // Calculate compliance issues
657
- const complianceIssues = auditResults.compliance
658
- ? (auditResults.compliance.customAuthCode.length +
659
- auditResults.compliance.restrictedImports.length +
660
- auditResults.compliance.duplicateComponents.length +
661
- auditResults.compliance.duplicateHooks.length +
662
- auditResults.compliance.duplicateUtils.length +
663
- auditResults.compliance.unprotectedPages.length +
664
- auditResults.compliance.directSupabaseAuth.length +
665
- auditResults.compliance.providerSetupIssues.length +
666
- auditResults.compliance.viteConfigIssues.length +
667
- auditResults.compliance.routerSetupIssues.length +
668
- auditResults.compliance.duplicateConfig.length)
669
- : 0;
670
-
671
- const totalIssues = phase1Errors + phase1Warnings + phase2Suggestions + complianceIssues;
672
-
673
- // Calculate compliance score (0-100)
674
- const maxIssues = 100; // Arbitrary max for scoring
675
- const complianceScore = Math.max(0, 100 - Math.min(100, (totalIssues / maxIssues) * 100));
676
-
677
- // Generate markdown
678
- let markdown = `# pace-core Compliance Audit Report\n\n`;
679
- markdown += `**Generated:** ${timestamp.toISOString()}\n`;
680
- markdown += `**Project:** ${packageJson?.name || 'Unknown'}\n`;
681
- markdown += `**pace-core Version:** ${paceCoreVersion}\n`;
682
- markdown += `**Audit Tool Version:** 1.0.0\n\n`;
683
-
684
- markdown += `## Executive Summary\n\n`;
685
- markdown += `- **Total Issues:** ${totalIssues}\n`;
686
- markdown += `- **Critical Failures:** ${phase1Errors} (Phase 1 - Must Fix)\n`;
687
- markdown += `- **Warnings:** ${phase1Warnings} (Phase 1 - Should Fix)\n`;
688
- markdown += `- **Suggestions:** ${phase2Suggestions} (Phase 2 - Consider)\n`;
689
- markdown += `- **Compliance Issues:** ${complianceIssues} (pace-core Compliance Check)\n`;
690
- markdown += `- **Compliance Score:** ${complianceScore.toFixed(1)}%\n\n`;
691
-
692
- // Phase 1: Deterministic Checks
693
- markdown += `## Phase 1: Deterministic Checks\n\n`;
694
-
695
- // File Structure
696
- if (auditResults.phase1.fileStructure.issues.length > 0 || auditResults.phase1.fileStructure.warnings.length > 0) {
697
- markdown += `### File Structure\n\n`;
698
- auditResults.phase1.fileStructure.issues.forEach(issue => {
699
- markdown += `- [ ] ❌ **${issue.directory}**: ${issue.message}\n`;
700
- });
701
- auditResults.phase1.fileStructure.warnings.forEach(warning => {
702
- markdown += `- [ ] ⚠️ **${warning.directory}**: ${warning.message}\n`;
703
- });
704
- markdown += `\n`;
705
- } else {
706
- markdown += `### File Structure\n\n`;
707
- markdown += `- [x] ✅ All required directories present\n\n`;
708
- }
709
-
710
- // Config Files
711
- if (auditResults.phase1.configFiles.issues.length > 0 || auditResults.phase1.configFiles.warnings.length > 0) {
712
- markdown += `### Config Files\n\n`;
713
- auditResults.phase1.configFiles.issues.forEach(issue => {
714
- markdown += `- [ ] ❌ **${issue.file}**: ${issue.message}\n`;
715
- });
716
- auditResults.phase1.configFiles.warnings.forEach(warning => {
717
- markdown += `- [ ] ⚠️ **${warning.file}**: ${warning.message}\n`;
718
- });
719
- markdown += `\n`;
720
- } else {
721
- markdown += `### Config Files\n\n`;
722
- markdown += `- [x] ✅ All required config files present\n\n`;
723
- }
724
-
725
- // TypeScript Config
726
- if (auditResults.phase1.typescript.issues.length > 0 || auditResults.phase1.typescript.warnings.length > 0) {
727
- markdown += `### TypeScript Configuration\n\n`;
728
- auditResults.phase1.typescript.issues.forEach(issue => {
729
- markdown += `- [ ] ❌ ${issue.message}\n`;
730
- if (issue.recommendation) {
731
- markdown += ` - Recommendation: ${issue.recommendation}\n`;
732
- }
733
- });
734
- auditResults.phase1.typescript.warnings.forEach(warning => {
735
- markdown += `- [ ] ⚠️ ${warning.message}\n`;
736
- });
737
- markdown += `\n`;
738
- } else {
739
- markdown += `### TypeScript Configuration\n\n`;
740
- markdown += `- [x] ✅ TypeScript strict mode enabled\n\n`;
741
- }
742
-
743
- // Test Coverage
744
- if (auditResults.phase1.coverage.warnings.length > 0) {
745
- markdown += `### Test Coverage\n\n`;
746
- if (auditResults.phase1.coverage.metrics) {
747
- const m = auditResults.phase1.coverage.metrics;
748
- markdown += `**Current Coverage:**\n`;
749
- markdown += `- Lines: ${m.lines.toFixed(1)}%\n`;
750
- markdown += `- Functions: ${m.functions.toFixed(1)}%\n`;
751
- markdown += `- Branches: ${m.branches.toFixed(1)}%\n`;
752
- markdown += `- Statements: ${m.statements.toFixed(1)}%\n\n`;
753
- }
754
- auditResults.phase1.coverage.warnings.forEach(warning => {
755
- markdown += `- [ ] ⚠️ ${warning.message}\n`;
756
- });
757
- markdown += `\n`;
758
- } else if (auditResults.phase1.coverage.metrics) {
759
- markdown += `### Test Coverage\n\n`;
760
- const m = auditResults.phase1.coverage.metrics;
761
- markdown += `- [x] ✅ Coverage meets requirements\n`;
762
- markdown += ` - Lines: ${m.lines.toFixed(1)}%\n`;
763
- markdown += ` - Functions: ${m.functions.toFixed(1)}%\n`;
764
- markdown += ` - Branches: ${m.branches.toFixed(1)}%\n`;
765
- markdown += ` - Statements: ${m.statements.toFixed(1)}%\n\n`;
766
- }
767
-
768
- // Phase 2: Heuristic Checks
769
- markdown += `## Phase 2: Heuristic Checks (Suggestions)\n\n`;
770
-
771
- if (auditResults.phase2.suggestions.length === 0) {
772
- markdown += `- ✅ No suggestions at this time\n\n`;
773
- } else {
774
- // Group by type
775
- const byType = {};
776
- auditResults.phase2.suggestions.forEach(suggestion => {
777
- if (!byType[suggestion.type]) {
778
- byType[suggestion.type] = [];
779
- }
780
- byType[suggestion.type].push(suggestion);
781
- });
782
-
783
- Object.entries(byType).forEach(([type, suggestions]) => {
784
- const typeName = type.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
785
- markdown += `### ${typeName}\n\n`;
786
- suggestions.forEach(suggestion => {
787
- markdown += `- 💡 **${suggestion.file}**: ${suggestion.message}\n`;
788
- if (suggestion.lines) {
789
- markdown += ` - Lines: ${suggestion.lines}\n`;
790
- }
791
- if (suggestion.exportCount) {
792
- markdown += ` - Exports: ${suggestion.exportCount}\n`;
793
- }
794
- });
795
- markdown += `\n`;
796
- });
797
- }
798
-
799
- // Compliance Check Results
800
- markdown += `## pace-core Compliance Check\n\n`;
801
- if (auditResults.compliance) {
802
- markdown += complianceViolationsToMarkdown(auditResults.compliance);
803
- } else {
804
- markdown += `⚠️ Compliance check was not run. Run the audit script to include compliance results.\n\n`;
805
- }
806
-
807
- // Recommendations
808
- markdown += `## Recommendations\n\n`;
809
-
810
- if (phase1Errors > 0) {
811
- markdown += `### Must Fix (Phase 1 Failures)\n\n`;
812
- auditResults.phase1.issues.forEach(issue => {
813
- markdown += `1. **Priority: High** - ${issue.message || issue.type}\n`;
814
- if (issue.recommendation) {
815
- markdown += ` - ${issue.recommendation}\n`;
816
- }
817
- });
818
- markdown += `\n`;
819
- }
820
-
821
- if (phase1Warnings > 0) {
822
- markdown += `### Should Fix (Phase 1 Warnings)\n\n`;
823
- auditResults.phase1.warnings.forEach(warning => {
824
- markdown += `1. **Priority: Medium** - ${warning.message || warning.type}\n`;
825
- if (warning.recommendation) {
826
- markdown += ` - ${warning.recommendation}\n`;
827
- }
828
- });
829
- markdown += `\n`;
830
- }
831
-
832
- if (phase2Suggestions > 0) {
833
- markdown += `### Consider (Phase 2 Suggestions)\n\n`;
834
- auditResults.phase2.suggestions.slice(0, 10).forEach(suggestion => {
835
- markdown += `1. **Priority: Low** - ${suggestion.message}\n`;
836
- markdown += ` - File: ${suggestion.file}\n`;
837
- });
838
- if (phase2Suggestions > 10) {
839
- markdown += `\n*... and ${phase2Suggestions - 10} more suggestions*\n`;
840
- }
841
- markdown += `\n`;
842
- }
843
-
844
- if (totalIssues === 0) {
845
- markdown += `✅ **Excellent!** No issues found. Your codebase is fully compliant.\n\n`;
846
- }
847
-
848
- // Write report
849
- fs.writeFileSync(reportPath, markdown, 'utf8');
850
-
851
- return { reportPath, filename };
852
- }
853
-
854
- // Main function
855
- function main() {
856
- const projectRoot = findProjectRoot();
857
- const packageJson = getPackageInfo(projectRoot);
858
- const paceCoreVersion = getPaceCoreVersion(packageJson);
859
-
860
- console.log(`${colors.cyan}${colors.bold}═══════════════════════════════════════════════════════════${colors.reset}`);
861
- console.log(`${colors.cyan}${colors.bold} pace-core Comprehensive Audit${colors.reset}`);
862
- console.log(`${colors.cyan}${colors.bold}═══════════════════════════════════════════════════════════${colors.reset}\n`);
863
- console.log(`${colors.cyan}Project:${colors.reset} ${packageJson?.name || 'Unknown'}`);
864
- console.log(`${colors.cyan}Root:${colors.reset} ${projectRoot}`);
865
- console.log(`${colors.cyan}pace-core Version:${colors.reset} ${paceCoreVersion}\n`);
866
-
867
- // Note: We don't call complianceChecker.main() because it calls process.exit()
868
- // The compliance check output you see is from a previous run or separate execution
869
- // We'll continue with Phase 1 and Phase 2 checks and generate markdown report
870
-
871
- // Phase 1: Deterministic Checks
872
- console.log(`\n${colors.cyan}Phase 1: Running deterministic checks...${colors.reset}`);
873
- const fileStructure = checkFileStructure(projectRoot);
874
- const configFiles = checkConfigFiles(projectRoot);
875
- const typescript = checkTypeScriptConfig(projectRoot);
876
- const coverage = checkTestCoverage(projectRoot);
877
-
878
- const phase1 = {
879
- issues: [
880
- ...fileStructure.issues,
881
- ...configFiles.issues,
882
- ...typescript.issues,
883
- ...coverage.issues
884
- ],
885
- warnings: [
886
- ...fileStructure.warnings,
887
- ...configFiles.warnings,
888
- ...typescript.warnings,
889
- ...coverage.warnings
890
- ],
891
- fileStructure,
892
- configFiles,
893
- typescript,
894
- coverage
895
- };
896
-
897
- // Phase 2: Heuristic Checks
898
- console.log(`${colors.cyan}Phase 2: Running heuristic checks...${colors.reset}`);
899
- const largeFiles = checkLargeFiles(projectRoot);
900
- const godObjects = checkGodObjects(projectRoot);
901
-
902
- const phase2 = {
903
- suggestions: [
904
- ...largeFiles,
905
- ...godObjects
906
- ]
907
- };
908
-
909
- // Compliance Check
910
- console.log(`${colors.cyan}Running pace-core compliance check...${colors.reset}`);
911
- let complianceResults = null;
912
- try {
913
- complianceResults = runComplianceCheck(projectRoot);
914
- console.log(`${colors.green}✓ Compliance check complete${colors.reset}`);
915
- } catch (error) {
916
- console.error(`${colors.red}Compliance check failed: ${error.message}${colors.reset}`);
917
- if (error.stack) {
918
- console.error(`${colors.red}Stack: ${error.stack}${colors.reset}`);
919
- }
920
- console.error(`${colors.yellow}Continuing with other audit checks...${colors.reset}`);
921
- }
922
-
923
- // Generate report
924
- console.log(`\n${colors.cyan}Generating audit report...${colors.reset}`);
925
- const auditResults = { phase1, phase2, compliance: complianceResults };
926
- const { reportPath, filename } = generateMarkdownReport(
927
- auditResults,
928
- projectRoot,
929
- packageJson,
930
- paceCoreVersion
931
- );
932
-
933
- console.log(`\n${colors.green}${colors.bold}✅ Audit complete!${colors.reset}`);
934
- console.log(`${colors.green}Report saved to: ${reportPath}${colors.reset}\n`);
935
-
936
- // Summary
937
- const totalErrors = phase1.issues.length;
938
- const totalWarnings = phase1.warnings.length;
939
- const totalSuggestions = phase2.suggestions.length;
940
-
941
- console.log(`${colors.bold}Summary:${colors.reset}`);
942
- console.log(` ${colors.red}Critical Failures:${colors.reset} ${totalErrors}`);
943
- console.log(` ${colors.yellow}Warnings:${colors.reset} ${totalWarnings}`);
944
- console.log(` ${colors.blue}Suggestions:${colors.reset} ${totalSuggestions}`);
945
- console.log(`\n${colors.cyan}See ${filename} for detailed report.${colors.reset}\n`);
946
-
947
- process.exit(totalErrors > 0 ? 1 : 0);
948
- }
78
+ child.on('error', (error) => {
79
+ console.error(`Error running audit script: ${error.message}`);
80
+ process.exit(1);
81
+ });
949
82
 
950
- // Run if called directly
951
- if (require.main === module) {
952
- try {
953
- main();
954
- } catch (error) {
955
- console.error(`${colors.red}Error: ${error.message}${colors.reset}`);
956
- console.error(error.stack);
957
- process.exit(1);
958
- }
959
- }
83
+ child.on('exit', (code) => {
84
+ process.exit(code || 0);
85
+ });
960
86
 
961
- module.exports = { main };