@jmruthers/pace-core 0.6.1 → 0.6.3

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 (549) hide show
  1. package/CHANGELOG.md +88 -10
  2. package/cursor-rules/00-pace-core-compliance.mdc +46 -87
  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-Cb34EQs3.d.ts} +63 -1
  14. package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
  15. package/dist/{DataTable-DQ7RSOHE.js → DataTable-THFPBKTP.js} +12 -10
  16. package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DEMpysFR.d.ts} +394 -171
  17. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CKvHP1MK.d.ts} +30 -8
  18. package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-KAGUYQ4J.js} +5 -4
  19. package/dist/{api-N774RPUA.js → api-IAGWF3ZG.js} +10 -10
  20. package/dist/{audit-B5P6FFIR.js → audit-V53FV5AG.js} +2 -2
  21. package/dist/{chunk-JBKQ3SAO.js → chunk-2T2IG7T7.js} +107 -57
  22. package/dist/chunk-2T2IG7T7.js.map +1 -0
  23. package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
  24. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  25. package/dist/{chunk-3XTALGJF.js → chunk-6Z7LTB3D.js} +69 -240
  26. package/dist/chunk-6Z7LTB3D.js.map +1 -0
  27. package/dist/{chunk-4ZC4GX36.js → chunk-CNCQDFLN.js} +199 -46
  28. package/dist/chunk-CNCQDFLN.js.map +1 -0
  29. package/dist/chunk-DGUM43GV.js +11 -0
  30. package/dist/{chunk-BYFSK72L.js → chunk-DWUBLJJM.js} +361 -187
  31. package/dist/chunk-DWUBLJJM.js.map +1 -0
  32. package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
  33. package/dist/chunk-FFQEQTNW.js.map +1 -0
  34. package/dist/chunk-FMUCXFII.js +76 -0
  35. package/dist/chunk-FMUCXFII.js.map +1 -0
  36. package/dist/{chunk-4N5C5XZU.js → chunk-HFZBI76P.js} +4 -4
  37. package/dist/chunk-HFZBI76P.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-I7PSE6JW.js → chunk-M7MPQISP.js} +3 -76
  43. package/dist/chunk-M7MPQISP.js.map +1 -0
  44. package/dist/chunk-PQBSKX33.js +7793 -0
  45. package/dist/chunk-PQBSKX33.js.map +1 -0
  46. package/dist/chunk-QRPVRXYT.js +226 -0
  47. package/dist/chunk-QRPVRXYT.js.map +1 -0
  48. package/dist/{chunk-KNC55RTG.js → chunk-RWEBCB47.js} +194 -416
  49. package/dist/chunk-RWEBCB47.js.map +1 -0
  50. package/dist/{chunk-XM25TVIE.js → chunk-YDQHOZNA.js} +843 -388
  51. package/dist/chunk-YDQHOZNA.js.map +1 -0
  52. package/dist/{chunk-GLK6VM3F.js → chunk-ZNIWI3UC.js} +739 -737
  53. package/dist/chunk-ZNIWI3UC.js.map +1 -0
  54. package/dist/components.d.ts +5 -5
  55. package/dist/components.js +18 -16
  56. package/dist/components.js.map +1 -1
  57. package/dist/contextValidator-3JNZKUTX.js +9 -0
  58. package/dist/contextValidator-3JNZKUTX.js.map +1 -0
  59. package/dist/eslint-rules/pace-core-compliance.cjs +106 -0
  60. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  61. package/dist/hooks.d.ts +55 -122
  62. package/dist/hooks.js +10 -13
  63. package/dist/hooks.js.map +1 -1
  64. package/dist/index.d.ts +60 -13
  65. package/dist/index.js +30 -25
  66. package/dist/index.js.map +1 -1
  67. package/dist/providers.d.ts +21 -3
  68. package/dist/providers.js +4 -3
  69. package/dist/rbac/index.d.ts +210 -139
  70. package/dist/rbac/index.js +17 -13
  71. package/dist/styles/index.js +1 -1
  72. package/dist/theming/runtime.d.ts +1 -13
  73. package/dist/theming/runtime.js +2 -2
  74. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  75. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  76. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  77. package/dist/types.d.ts +2 -2
  78. package/dist/types.js +1 -1
  79. package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-i3qtoBgg.d.ts} +38 -17
  80. package/dist/utils.d.ts +4 -5
  81. package/dist/utils.js +17 -19
  82. package/dist/utils.js.map +1 -1
  83. package/docs/api/README.md +21 -17
  84. package/docs/api/modules.md +4191 -2967
  85. package/docs/architecture/database-schema-requirements.md +161 -0
  86. package/docs/components/context-selector.md +126 -0
  87. package/docs/core-concepts/rbac-system.md +3 -3
  88. package/docs/documentation-index.md +2 -4
  89. package/docs/getting-started/cursor-rules.md +2 -1
  90. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  91. package/docs/migration/MIGRATION_GUIDE.md +2 -24
  92. package/docs/migration/RBAC_SCOPE_MIGRATION.md +385 -0
  93. package/docs/migration/README.md +52 -6
  94. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  95. package/docs/migration/database-changes-december-2025.md +3 -3
  96. package/docs/pace-mint-fix-auto-selection.md +218 -0
  97. package/docs/pace-mint-rbac-setup.md +391 -0
  98. package/docs/rbac/event-based-apps.md +1 -1
  99. package/docs/rbac/getting-started.md +1 -1
  100. package/docs/rbac/quick-start.md +1 -1
  101. package/docs/rbac/secure-client-protection.md +330 -0
  102. package/docs/standards/README.md +1 -0
  103. package/package.json +4 -3
  104. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  105. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  106. package/scripts/audit/core/checks/bundle.cjs +142 -0
  107. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +784 -685
  108. package/scripts/audit/core/checks/config.cjs +54 -0
  109. package/scripts/audit/core/checks/coverage.cjs +84 -0
  110. package/scripts/audit/core/checks/dependencies.cjs +985 -0
  111. package/scripts/audit/core/checks/documentation.cjs +268 -0
  112. package/scripts/audit/core/checks/environment.cjs +116 -0
  113. package/scripts/audit/core/checks/error-handling.cjs +340 -0
  114. package/scripts/audit/core/checks/forms.cjs +172 -0
  115. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  116. package/scripts/audit/core/checks/hooks.cjs +334 -0
  117. package/scripts/audit/core/checks/imports.cjs +244 -0
  118. package/scripts/audit/core/checks/performance.cjs +325 -0
  119. package/scripts/audit/core/checks/routes.cjs +117 -0
  120. package/scripts/audit/core/checks/state.cjs +130 -0
  121. package/scripts/audit/core/checks/structure.cjs +65 -0
  122. package/scripts/audit/core/checks/style.cjs +584 -0
  123. package/scripts/audit/core/checks/testing.cjs +122 -0
  124. package/scripts/audit/core/checks/typescript.cjs +61 -0
  125. package/scripts/audit/core/scanner.cjs +199 -0
  126. package/scripts/audit/core/utils.cjs +137 -0
  127. package/scripts/audit/index.cjs +223 -0
  128. package/scripts/audit/reporters/console.cjs +151 -0
  129. package/scripts/audit/reporters/json.cjs +54 -0
  130. package/scripts/audit/reporters/markdown.cjs +124 -0
  131. package/scripts/audit-consuming-app.cjs +61 -936
  132. package/scripts/build-docs/build-decision.js +240 -0
  133. package/scripts/build-docs/cache-utils.js +105 -0
  134. package/scripts/build-docs/content-normalization.js +150 -0
  135. package/scripts/build-docs/file-utils.js +105 -0
  136. package/scripts/build-docs/git-utils.js +86 -0
  137. package/scripts/build-docs/hash-utils.js +116 -0
  138. package/scripts/build-docs/typedoc-runner.js +220 -0
  139. package/scripts/build-docs-incremental.js +77 -913
  140. package/scripts/utils/command-runner.js +16 -11
  141. package/scripts/validate-formats.js +61 -56
  142. package/scripts/validate-master.js +74 -69
  143. package/scripts/validate-pre-publish.js +70 -65
  144. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  145. package/src/components/Alert/Alert.test.tsx +12 -18
  146. package/src/components/Alert/Alert.tsx +5 -7
  147. package/src/components/Avatar/Avatar.test.tsx +4 -4
  148. package/src/components/Badge/Badge.tsx +14 -0
  149. package/src/components/Button/Button.tsx +22 -0
  150. package/src/components/Calendar/Calendar.tsx +8 -2
  151. package/src/components/Card/Card.tsx +4 -0
  152. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  153. package/src/components/Checkbox/Checkbox.tsx +2 -2
  154. package/src/components/ContextSelector/ContextSelector.tsx +384 -0
  155. package/src/components/ContextSelector/index.ts +3 -0
  156. package/src/components/DataTable/DataTable.tsx +38 -4
  157. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  158. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
  159. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  160. package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
  161. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  162. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  163. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  164. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  165. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  166. package/src/components/DataTable/components/DataTableCore.tsx +196 -554
  167. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  168. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  169. package/src/components/DataTable/components/DataTableModals.tsx +8 -0
  170. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  171. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  172. package/src/components/DataTable/components/EditFields.tsx +307 -0
  173. package/src/components/DataTable/components/EditableRow.tsx +8 -0
  174. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  175. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  176. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  177. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  178. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  179. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  180. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  181. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  182. package/src/components/DataTable/components/UnifiedTableBody.tsx +63 -851
  183. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  184. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  185. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  186. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  187. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  188. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  189. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  190. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  191. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  192. package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
  193. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  194. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  195. package/src/components/DataTable/hooks/useDataTablePermissions.ts +127 -33
  196. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  197. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  198. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  199. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  200. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  201. package/src/components/DataTable/styles.ts +6 -6
  202. package/src/components/DataTable/types.ts +6 -10
  203. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  204. package/src/components/DataTable/utils/debugTools.ts +18 -113
  205. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  206. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  207. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  208. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  209. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  210. package/src/components/Dialog/Dialog.tsx +31 -3
  211. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  212. package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
  213. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  214. package/src/components/ErrorBoundary/index.ts +27 -2
  215. package/src/components/FileDisplay/FileDisplay.tsx +74 -28
  216. package/src/components/FileUpload/FileUpload.tsx +22 -2
  217. package/src/components/Footer/Footer.test.tsx +16 -16
  218. package/src/components/Footer/Footer.tsx +14 -11
  219. package/src/components/Form/Form.tsx +1 -0
  220. package/src/components/Header/Header.test.tsx +43 -73
  221. package/src/components/Header/Header.tsx +59 -49
  222. package/src/components/Input/Input.test.tsx +2 -2
  223. package/src/components/Input/Input.tsx +8 -4
  224. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  225. package/src/components/LoginForm/LoginForm.tsx +4 -0
  226. package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
  227. package/src/components/NavigationMenu/types.ts +56 -0
  228. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  229. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +10 -19
  230. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +2 -2
  231. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +5 -5
  232. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +13 -11
  233. package/src/components/PaceAppLayout/PaceAppLayout.tsx +167 -44
  234. package/src/components/PaceAppLayout/README.md +14 -17
  235. package/src/components/PaceAppLayout/test-setup.tsx +3 -4
  236. package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
  237. package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
  238. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  239. package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
  240. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  241. package/src/components/Select/Select.tsx +80 -434
  242. package/src/components/Select/context.ts +23 -0
  243. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  244. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  245. package/src/components/Select/hooks/useSelectState.ts +104 -0
  246. package/src/components/Select/index.ts +9 -1
  247. package/src/components/Select/types.ts +123 -0
  248. package/src/components/Select/utils/text.ts +26 -0
  249. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
  250. package/src/components/Switch/Switch.tsx +4 -4
  251. package/src/components/Tabs/Tabs.tsx +1 -1
  252. package/src/components/Toast/Toast.tsx +4 -0
  253. package/src/components/Tooltip/Tooltip.tsx +2 -2
  254. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  255. package/src/components/UserMenu/UserMenu.tsx +21 -18
  256. package/src/components/index.ts +7 -7
  257. package/src/eslint-rules/pace-core-compliance.cjs +106 -0
  258. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  259. package/src/hooks/__tests__/useAppConfig.unit.test.ts +4 -98
  260. package/src/hooks/index.ts +1 -2
  261. package/src/hooks/public/usePublicEvent.ts +4 -0
  262. package/src/hooks/public/usePublicEventLogo.ts +4 -0
  263. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  264. package/src/hooks/public/usePublicRouteParams.ts +4 -0
  265. package/src/hooks/services/useAuth.ts +32 -0
  266. package/src/hooks/services/useCurrentEvent.ts +6 -0
  267. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  268. package/src/hooks/useAppConfig.ts +15 -30
  269. package/src/hooks/useDebounce.ts +9 -0
  270. package/src/hooks/useEventTheme.ts +6 -0
  271. package/src/hooks/useFileDisplay.ts +81 -50
  272. package/src/hooks/useFileReference.ts +25 -7
  273. package/src/hooks/useFileUrl.ts +11 -1
  274. package/src/hooks/useFocusManagement.ts +14 -0
  275. package/src/hooks/useFocusTrap.ts +3 -0
  276. package/src/hooks/useInactivityTracker.ts +3 -0
  277. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  278. package/src/hooks/useOrganisationPermissions.ts +4 -0
  279. package/src/hooks/useOrganisationSecurity.ts +4 -0
  280. package/src/hooks/usePerformanceMonitor.ts +4 -0
  281. package/src/hooks/usePermissionCache.ts +7 -0
  282. package/src/hooks/useQueryCache.ts +12 -1
  283. package/src/hooks/useSessionRestoration.ts +4 -0
  284. package/src/hooks/useStorage.ts +4 -0
  285. package/src/hooks/useToast.ts +1 -1
  286. package/src/index.ts +6 -6
  287. package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
  288. package/src/providers/services/AuthServiceProvider.tsx +35 -7
  289. package/src/providers/services/EventServiceProvider.tsx +51 -5
  290. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  291. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +126 -134
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
  294. package/src/rbac/README.md +1 -1
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +1 -1
  296. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  297. package/src/rbac/adapters.tsx +12 -3
  298. package/src/rbac/api.test.ts +59 -51
  299. package/src/rbac/api.ts +246 -167
  300. package/src/rbac/components/NavigationProvider.tsx +4 -1
  301. package/src/rbac/components/PagePermissionGuard.tsx +185 -17
  302. package/src/rbac/components/RoleBasedRouter.tsx +5 -1
  303. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  304. package/src/rbac/components/SecureDataProvider.tsx +20 -5
  305. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  306. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  307. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  308. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  309. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  310. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  311. package/src/rbac/engine.ts +38 -14
  312. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +32 -21
  313. package/src/rbac/hooks/permissions/index.ts +7 -0
  314. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  315. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  316. package/src/rbac/hooks/permissions/useCan.ts +377 -0
  317. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  318. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  319. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  320. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  321. package/src/rbac/hooks/useCan.test.ts +64 -66
  322. package/src/rbac/hooks/usePermissions.ts +14 -995
  323. package/src/rbac/hooks/useRBAC.test.ts +1 -5
  324. package/src/rbac/hooks/useRBAC.ts +36 -37
  325. package/src/rbac/hooks/useResolvedScope.test.ts +120 -35
  326. package/src/rbac/hooks/useResolvedScope.ts +35 -40
  327. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  328. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  329. package/src/rbac/hooks/useSecureSupabase.ts +27 -7
  330. package/src/rbac/index.ts +7 -0
  331. package/src/rbac/permissions.ts +0 -30
  332. package/src/rbac/secureClient.test.ts +22 -18
  333. package/src/rbac/secureClient.ts +294 -68
  334. package/src/rbac/security.ts +0 -17
  335. package/src/rbac/types.ts +9 -0
  336. package/src/rbac/utils/__tests__/contextValidator.test.ts +64 -86
  337. package/src/rbac/utils/clientSecurity.ts +93 -0
  338. package/src/rbac/utils/contextValidator.ts +77 -168
  339. package/src/services/AuthService.ts +39 -7
  340. package/src/services/EventService.ts +186 -54
  341. package/src/services/OrganisationService.ts +81 -14
  342. package/src/services/__tests__/EventService.test.ts +1 -2
  343. package/src/services/base/BaseService.ts +3 -0
  344. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  345. package/src/theming/parseEventColours.ts +5 -19
  346. package/src/types/vitest-globals.d.ts +51 -26
  347. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  348. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  349. package/src/utils/__tests__/index.unit.test.ts +2 -2
  350. package/src/utils/audit/audit.ts +0 -3
  351. package/src/utils/core/cn.ts +1 -1
  352. package/src/utils/dynamic/dynamicUtils.ts +7 -4
  353. package/src/utils/file-reference/index.ts +53 -1
  354. package/src/utils/formatting/formatting.ts +8 -18
  355. package/src/utils/index.ts +0 -1
  356. package/dist/chunk-3QRJFVBR.js.map +0 -1
  357. package/dist/chunk-3XTALGJF.js.map +0 -1
  358. package/dist/chunk-4N5C5XZU.js.map +0 -1
  359. package/dist/chunk-4ZC4GX36.js.map +0 -1
  360. package/dist/chunk-7D4SUZUM.js +0 -38
  361. package/dist/chunk-BYFSK72L.js.map +0 -1
  362. package/dist/chunk-EXUD6RNJ.js +0 -451
  363. package/dist/chunk-EXUD6RNJ.js.map +0 -1
  364. package/dist/chunk-GLK6VM3F.js.map +0 -1
  365. package/dist/chunk-I7PSE6JW.js.map +0 -1
  366. package/dist/chunk-JBKQ3SAO.js.map +0 -1
  367. package/dist/chunk-KNC55RTG.js.map +0 -1
  368. package/dist/chunk-LXQLPRQ2.js.map +0 -1
  369. package/dist/chunk-R77UEZ4E.js.map +0 -1
  370. package/dist/chunk-SQGMNID3.js.map +0 -1
  371. package/dist/chunk-T33XF5ZC.js +0 -12922
  372. package/dist/chunk-T33XF5ZC.js.map +0 -1
  373. package/dist/chunk-XM25TVIE.js.map +0 -1
  374. package/docs/api/classes/ColumnFactory.md +0 -243
  375. package/docs/api/classes/ErrorBoundary.md +0 -144
  376. package/docs/api/classes/InvalidScopeError.md +0 -73
  377. package/docs/api/classes/Logger.md +0 -178
  378. package/docs/api/classes/MissingUserContextError.md +0 -66
  379. package/docs/api/classes/OrganisationContextRequiredError.md +0 -66
  380. package/docs/api/classes/PermissionDeniedError.md +0 -73
  381. package/docs/api/classes/RBACAuditManager.md +0 -297
  382. package/docs/api/classes/RBACCache.md +0 -322
  383. package/docs/api/classes/RBACEngine.md +0 -171
  384. package/docs/api/classes/RBACError.md +0 -76
  385. package/docs/api/classes/RBACNotInitializedError.md +0 -66
  386. package/docs/api/classes/SecureSupabaseClient.md +0 -160
  387. package/docs/api/classes/StorageUtils.md +0 -328
  388. package/docs/api/enums/FileCategory.md +0 -184
  389. package/docs/api/enums/LogLevel.md +0 -54
  390. package/docs/api/enums/RBACErrorCode.md +0 -228
  391. package/docs/api/enums/RPCFunction.md +0 -118
  392. package/docs/api/interfaces/AddressFieldProps.md +0 -241
  393. package/docs/api/interfaces/AddressFieldRef.md +0 -94
  394. package/docs/api/interfaces/AggregateConfig.md +0 -43
  395. package/docs/api/interfaces/AutocompleteOptions.md +0 -75
  396. package/docs/api/interfaces/AvatarProps.md +0 -128
  397. package/docs/api/interfaces/BadgeProps.md +0 -27
  398. package/docs/api/interfaces/ButtonProps.md +0 -53
  399. package/docs/api/interfaces/CalendarProps.md +0 -70
  400. package/docs/api/interfaces/CardProps.md +0 -66
  401. package/docs/api/interfaces/ColorPalette.md +0 -7
  402. package/docs/api/interfaces/ColorShade.md +0 -66
  403. package/docs/api/interfaces/ComplianceResult.md +0 -30
  404. package/docs/api/interfaces/DataAccessRecord.md +0 -96
  405. package/docs/api/interfaces/DataRecord.md +0 -11
  406. package/docs/api/interfaces/DataTableAction.md +0 -249
  407. package/docs/api/interfaces/DataTableColumn.md +0 -504
  408. package/docs/api/interfaces/DataTableProps.md +0 -625
  409. package/docs/api/interfaces/DataTableToolbarButton.md +0 -96
  410. package/docs/api/interfaces/DatabaseComplianceResult.md +0 -85
  411. package/docs/api/interfaces/DatabaseIssue.md +0 -41
  412. package/docs/api/interfaces/EmptyStateConfig.md +0 -61
  413. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +0 -235
  414. package/docs/api/interfaces/EventAppRoleData.md +0 -71
  415. package/docs/api/interfaces/ExportColumn.md +0 -90
  416. package/docs/api/interfaces/ExportOptions.md +0 -126
  417. package/docs/api/interfaces/FileDisplayProps.md +0 -249
  418. package/docs/api/interfaces/FileMetadata.md +0 -129
  419. package/docs/api/interfaces/FileReference.md +0 -118
  420. package/docs/api/interfaces/FileSizeLimits.md +0 -7
  421. package/docs/api/interfaces/FileUploadOptions.md +0 -139
  422. package/docs/api/interfaces/FileUploadProps.md +0 -293
  423. package/docs/api/interfaces/FooterProps.md +0 -105
  424. package/docs/api/interfaces/FormFieldProps.md +0 -166
  425. package/docs/api/interfaces/FormProps.md +0 -113
  426. package/docs/api/interfaces/GrantEventAppRoleParams.md +0 -122
  427. package/docs/api/interfaces/InactivityWarningModalProps.md +0 -115
  428. package/docs/api/interfaces/InputProps.md +0 -53
  429. package/docs/api/interfaces/LabelProps.md +0 -107
  430. package/docs/api/interfaces/LoggerConfig.md +0 -62
  431. package/docs/api/interfaces/LoginFormProps.md +0 -184
  432. package/docs/api/interfaces/NavigationAccessRecord.md +0 -107
  433. package/docs/api/interfaces/NavigationContextType.md +0 -164
  434. package/docs/api/interfaces/NavigationGuardProps.md +0 -139
  435. package/docs/api/interfaces/NavigationItem.md +0 -120
  436. package/docs/api/interfaces/NavigationMenuProps.md +0 -221
  437. package/docs/api/interfaces/NavigationProviderProps.md +0 -117
  438. package/docs/api/interfaces/Organisation.md +0 -140
  439. package/docs/api/interfaces/OrganisationContextType.md +0 -388
  440. package/docs/api/interfaces/OrganisationMembership.md +0 -140
  441. package/docs/api/interfaces/OrganisationProviderProps.md +0 -76
  442. package/docs/api/interfaces/OrganisationSecurityError.md +0 -62
  443. package/docs/api/interfaces/PaceAppLayoutProps.md +0 -406
  444. package/docs/api/interfaces/PaceLoginPageProps.md +0 -47
  445. package/docs/api/interfaces/PageAccessRecord.md +0 -85
  446. package/docs/api/interfaces/PagePermissionContextType.md +0 -140
  447. package/docs/api/interfaces/PagePermissionGuardProps.md +0 -153
  448. package/docs/api/interfaces/PagePermissionProviderProps.md +0 -119
  449. package/docs/api/interfaces/PaletteData.md +0 -41
  450. package/docs/api/interfaces/ParsedAddress.md +0 -120
  451. package/docs/api/interfaces/PermissionEnforcerProps.md +0 -153
  452. package/docs/api/interfaces/ProgressProps.md +0 -42
  453. package/docs/api/interfaces/ProtectedRouteProps.md +0 -97
  454. package/docs/api/interfaces/PublicPageFooterProps.md +0 -112
  455. package/docs/api/interfaces/PublicPageHeaderProps.md +0 -125
  456. package/docs/api/interfaces/PublicPageLayoutProps.md +0 -198
  457. package/docs/api/interfaces/QuickFix.md +0 -52
  458. package/docs/api/interfaces/RBACAccessValidateParams.md +0 -52
  459. package/docs/api/interfaces/RBACAccessValidateResult.md +0 -41
  460. package/docs/api/interfaces/RBACAuditLogParams.md +0 -85
  461. package/docs/api/interfaces/RBACAuditLogResult.md +0 -52
  462. package/docs/api/interfaces/RBACConfig.md +0 -133
  463. package/docs/api/interfaces/RBACContext.md +0 -52
  464. package/docs/api/interfaces/RBACLogger.md +0 -112
  465. package/docs/api/interfaces/RBACPageAccessCheckParams.md +0 -74
  466. package/docs/api/interfaces/RBACPerformanceMetrics.md +0 -138
  467. package/docs/api/interfaces/RBACPermissionCheckParams.md +0 -74
  468. package/docs/api/interfaces/RBACPermissionCheckResult.md +0 -52
  469. package/docs/api/interfaces/RBACPermissionsGetParams.md +0 -63
  470. package/docs/api/interfaces/RBACPermissionsGetResult.md +0 -63
  471. package/docs/api/interfaces/RBACResult.md +0 -58
  472. package/docs/api/interfaces/RBACRoleGrantParams.md +0 -63
  473. package/docs/api/interfaces/RBACRoleGrantResult.md +0 -52
  474. package/docs/api/interfaces/RBACRoleRevokeParams.md +0 -63
  475. package/docs/api/interfaces/RBACRoleRevokeResult.md +0 -52
  476. package/docs/api/interfaces/RBACRoleValidateParams.md +0 -52
  477. package/docs/api/interfaces/RBACRoleValidateResult.md +0 -63
  478. package/docs/api/interfaces/RBACRolesListParams.md +0 -52
  479. package/docs/api/interfaces/RBACRolesListResult.md +0 -74
  480. package/docs/api/interfaces/RBACSessionTrackParams.md +0 -74
  481. package/docs/api/interfaces/RBACSessionTrackResult.md +0 -52
  482. package/docs/api/interfaces/ResourcePermissions.md +0 -155
  483. package/docs/api/interfaces/RevokeEventAppRoleParams.md +0 -100
  484. package/docs/api/interfaces/RoleBasedRouterContextType.md +0 -151
  485. package/docs/api/interfaces/RoleBasedRouterProps.md +0 -156
  486. package/docs/api/interfaces/RoleManagementResult.md +0 -52
  487. package/docs/api/interfaces/RouteAccessRecord.md +0 -107
  488. package/docs/api/interfaces/RouteConfig.md +0 -134
  489. package/docs/api/interfaces/RuntimeComplianceResult.md +0 -55
  490. package/docs/api/interfaces/SecureDataContextType.md +0 -168
  491. package/docs/api/interfaces/SecureDataProviderProps.md +0 -132
  492. package/docs/api/interfaces/SessionRestorationLoaderProps.md +0 -34
  493. package/docs/api/interfaces/SetupIssue.md +0 -41
  494. package/docs/api/interfaces/StorageConfig.md +0 -41
  495. package/docs/api/interfaces/StorageFileInfo.md +0 -74
  496. package/docs/api/interfaces/StorageFileMetadata.md +0 -151
  497. package/docs/api/interfaces/StorageListOptions.md +0 -99
  498. package/docs/api/interfaces/StorageListResult.md +0 -41
  499. package/docs/api/interfaces/StorageUploadOptions.md +0 -101
  500. package/docs/api/interfaces/StorageUploadResult.md +0 -63
  501. package/docs/api/interfaces/StorageUrlOptions.md +0 -60
  502. package/docs/api/interfaces/StyleImport.md +0 -19
  503. package/docs/api/interfaces/SwitchProps.md +0 -34
  504. package/docs/api/interfaces/TabsContentProps.md +0 -9
  505. package/docs/api/interfaces/TabsListProps.md +0 -9
  506. package/docs/api/interfaces/TabsProps.md +0 -9
  507. package/docs/api/interfaces/TabsTriggerProps.md +0 -50
  508. package/docs/api/interfaces/TextareaProps.md +0 -53
  509. package/docs/api/interfaces/ToastActionElement.md +0 -9
  510. package/docs/api/interfaces/ToastProps.md +0 -9
  511. package/docs/api/interfaces/UnifiedAuthContextType.md +0 -820
  512. package/docs/api/interfaces/UnifiedAuthProviderProps.md +0 -171
  513. package/docs/api/interfaces/UseFormDialogOptions.md +0 -62
  514. package/docs/api/interfaces/UseFormDialogReturn.md +0 -117
  515. package/docs/api/interfaces/UseInactivityTrackerOptions.md +0 -136
  516. package/docs/api/interfaces/UseInactivityTrackerReturn.md +0 -123
  517. package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
  518. package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -81
  519. package/docs/api/interfaces/UsePublicEventOptions.md +0 -34
  520. package/docs/api/interfaces/UsePublicEventReturn.md +0 -68
  521. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +0 -47
  522. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +0 -120
  523. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +0 -94
  524. package/docs/api/interfaces/UseResolvedScopeOptions.md +0 -47
  525. package/docs/api/interfaces/UseResolvedScopeReturn.md +0 -47
  526. package/docs/api/interfaces/UseResourcePermissionsOptions.md +0 -34
  527. package/docs/api/interfaces/UserEventAccess.md +0 -118
  528. package/docs/api/interfaces/UserMenuProps.md +0 -86
  529. package/docs/api/interfaces/UserProfile.md +0 -63
  530. package/docs/migration/quick-migration-guide.md +0 -356
  531. package/docs/migration/service-architecture.md +0 -281
  532. package/src/components/EventSelector/EventSelector.test.tsx +0 -720
  533. package/src/components/EventSelector/EventSelector.tsx +0 -420
  534. package/src/components/EventSelector/index.ts +0 -3
  535. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +0 -784
  536. package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -324
  537. package/src/components/OrganisationSelector/index.ts +0 -9
  538. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  539. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  540. package/src/hooks/useSecureDataAccess.ts +0 -681
  541. /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-THFPBKTP.js.map} +0 -0
  542. /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-KAGUYQ4J.js.map} +0 -0
  543. /package/dist/{api-N774RPUA.js.map → api-IAGWF3ZG.js.map} +0 -0
  544. /package/dist/{audit-B5P6FFIR.js.map → audit-V53FV5AG.js.map} +0 -0
  545. /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
  546. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  547. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  548. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  549. /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 };