@jmruthers/pace-core 0.6.4 → 0.6.6

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 (387) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/core-usage-manifest.json +93 -0
  4. package/cursor-rules/00-pace-core-compliance.mdc +128 -26
  5. package/cursor-rules/01-standards-compliance.mdc +49 -8
  6. package/cursor-rules/02-project-structure.mdc +6 -0
  7. package/cursor-rules/03-solid-principles.mdc +2 -0
  8. package/cursor-rules/04-testing-standards.mdc +2 -0
  9. package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
  10. package/cursor-rules/06-code-quality.mdc +2 -0
  11. package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
  12. package/cursor-rules/08-markup-quality.mdc +52 -27
  13. package/cursor-rules/09-rbac-compliance.mdc +462 -0
  14. package/cursor-rules/10-error-handling-patterns.mdc +179 -0
  15. package/cursor-rules/11-performance-optimization.mdc +169 -0
  16. package/cursor-rules/12-ci-cd-integration.mdc +150 -0
  17. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  18. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
  19. package/dist/DataTable-LRJL4IRV.js +15 -0
  20. package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
  21. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  22. package/dist/api-Y4MQWOFW.js +4 -0
  23. package/dist/audit-MYQXYZFU.js +3 -0
  24. package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
  25. package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
  26. package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
  27. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  28. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  29. package/dist/chunk-4T7OBVTU.js +62 -0
  30. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  31. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  32. package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
  33. package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
  34. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  35. package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
  36. package/dist/chunk-C7NSAPTL.js +1 -0
  37. package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
  38. package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
  39. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  40. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  41. package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
  42. package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
  43. package/dist/chunk-MBADTM7L.js +64 -0
  44. package/dist/chunk-OHIK3MIO.js +994 -0
  45. package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
  46. package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
  47. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  48. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  49. package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
  50. package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
  51. package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
  52. package/dist/components.d.ts +6 -6
  53. package/dist/components.js +57 -267
  54. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  55. package/dist/eslint-rules/index.cjs +22 -0
  56. package/dist/eslint-rules/rules/compliance.cjs +348 -0
  57. package/dist/eslint-rules/rules/components.cjs +113 -0
  58. package/dist/eslint-rules/rules/imports.cjs +102 -0
  59. package/dist/eslint-rules/rules/rbac.cjs +790 -0
  60. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  61. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  62. package/dist/hooks.d.ts +5 -5
  63. package/dist/hooks.js +62 -270
  64. package/dist/icons/index.d.ts +1 -0
  65. package/dist/icons/index.js +1 -0
  66. package/dist/index.d.ts +36 -26
  67. package/dist/index.js +87 -690
  68. package/dist/providers.d.ts +2 -2
  69. package/dist/providers.js +8 -35
  70. package/dist/rbac/eslint-rules.d.ts +46 -44
  71. package/dist/rbac/eslint-rules.js +7 -4
  72. package/dist/rbac/index.d.ts +124 -594
  73. package/dist/rbac/index.js +14 -207
  74. package/dist/styles/index.js +2 -12
  75. package/dist/theming/runtime.js +3 -19
  76. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  77. package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
  78. package/dist/types-t9H8qKRw.d.ts +55 -0
  79. package/dist/types.d.ts +1 -1
  80. package/dist/types.js +7 -94
  81. package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
  82. package/dist/utils.d.ts +24 -117
  83. package/dist/utils.js +54 -392
  84. package/docs/README.md +16 -6
  85. package/docs/api/README.md +4 -402
  86. package/docs/api/modules.md +454 -930
  87. package/docs/api-reference/components.md +3 -1
  88. package/docs/api-reference/deprecated.md +31 -6
  89. package/docs/api-reference/rpc-functions.md +78 -3
  90. package/docs/best-practices/accessibility.md +6 -3
  91. package/docs/getting-started/cursor-rules.md +3 -23
  92. package/docs/getting-started/dependencies.md +650 -0
  93. package/docs/getting-started/installation-guide.md +20 -7
  94. package/docs/getting-started/quick-start.md +23 -12
  95. package/docs/implementation-guides/permission-enforcement.md +4 -0
  96. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  97. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  98. package/docs/rbac/README.md +12 -3
  99. package/docs/rbac/edge-functions-guide.md +376 -0
  100. package/docs/rbac/secure-client-protection.md +0 -34
  101. package/docs/standards/00-pace-core-compliance.md +967 -0
  102. package/docs/standards/01-standards-compliance.md +188 -0
  103. package/docs/standards/02-project-structure.md +985 -0
  104. package/docs/standards/03-solid-principles.md +39 -0
  105. package/docs/standards/04-testing-standards.md +36 -0
  106. package/docs/standards/05-bug-reports-and-features.md +27 -0
  107. package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
  108. package/docs/standards/07-tech-stack-compliance.md +30 -0
  109. package/docs/standards/08-markup-quality.md +345 -0
  110. package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
  111. package/docs/standards/10-error-handling-patterns.md +401 -0
  112. package/docs/standards/11-performance-optimization.md +348 -0
  113. package/docs/standards/12-ci-cd-integration.md +370 -0
  114. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
  115. package/docs/standards/README.md +62 -33
  116. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  117. package/eslint-config-pace-core.cjs +20 -4
  118. package/package.json +31 -21
  119. package/scripts/audit/audit-compliance.cjs +1295 -0
  120. package/scripts/audit/audit-components.cjs +260 -0
  121. package/scripts/audit/audit-dependencies.cjs +395 -0
  122. package/scripts/audit/audit-rbac.cjs +954 -0
  123. package/scripts/audit/audit-standards.cjs +1268 -0
  124. package/scripts/audit/index.cjs +1898 -194
  125. package/scripts/install-cursor-rules.cjs +259 -8
  126. package/scripts/validate-master.js +1 -1
  127. package/src/__tests__/fixtures/supabase.ts +1 -1
  128. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
  129. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  130. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  131. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
  132. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  133. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  134. package/src/__tests__/public-recipe-view.test.ts +38 -9
  135. package/src/components/Button/Button.tsx +5 -1
  136. package/src/components/ContextSelector/ContextSelector.tsx +42 -39
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
  138. package/src/components/DataTable/components/DataTableBody.tsx +55 -31
  139. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  140. package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
  141. package/src/components/DataTable/components/EditFields.tsx +23 -3
  142. package/src/components/DataTable/components/EditableRow.tsx +7 -2
  143. package/src/components/DataTable/components/ImportModal.tsx +4 -6
  144. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  145. package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
  146. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
  147. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
  148. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  149. package/src/components/DataTable/core/DataTableContext.tsx +1 -1
  150. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  151. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  152. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  153. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  154. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  155. package/src/components/DataTable/types.ts +5 -0
  156. package/src/components/DateTimeField/DateTimeField.tsx +20 -20
  157. package/src/components/DateTimeField/README.md +5 -2
  158. package/src/components/Dialog/Dialog.test.tsx +361 -318
  159. package/src/components/Dialog/Dialog.tsx +1154 -323
  160. package/src/components/Dialog/index.ts +3 -3
  161. package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
  162. package/src/components/FileDisplay/FileDisplay.tsx +28 -22
  163. package/src/components/Form/Form.test.tsx +9 -10
  164. package/src/components/Form/Form.tsx +369 -9
  165. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
  166. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
  167. package/src/components/LoginForm/LoginForm.tsx +2 -2
  168. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  169. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  170. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  171. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  172. package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
  173. package/src/components/PaceAppLayout/README.md +10 -9
  174. package/src/components/PaceAppLayout/test-setup.tsx +40 -31
  175. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  176. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  177. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
  178. package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
  179. package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
  180. package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
  181. package/src/components/Select/Select.tsx +23 -21
  182. package/src/components/Select/types.ts +1 -1
  183. package/src/components/UserMenu/UserMenu.test.tsx +38 -6
  184. package/src/components/UserMenu/UserMenu.tsx +39 -34
  185. package/src/components/index.ts +3 -4
  186. package/src/eslint-rules/index.cjs +22 -0
  187. package/src/eslint-rules/rules/compliance.cjs +348 -0
  188. package/src/eslint-rules/rules/components.cjs +113 -0
  189. package/src/eslint-rules/rules/imports.cjs +102 -0
  190. package/src/eslint-rules/rules/rbac.cjs +790 -0
  191. package/src/eslint-rules/utils/helpers.cjs +42 -0
  192. package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
  193. package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
  194. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  195. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  196. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  197. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  198. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  199. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  200. package/src/hooks/public/usePublicEvent.ts +62 -190
  201. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  202. package/src/hooks/public/usePublicEventLogo.ts +19 -9
  203. package/src/hooks/useAppConfig.ts +26 -24
  204. package/src/hooks/useEventTheme.test.ts +211 -233
  205. package/src/hooks/useEventTheme.ts +19 -28
  206. package/src/hooks/useEvents.ts +11 -7
  207. package/src/hooks/useKeyboardShortcuts.ts +1 -1
  208. package/src/hooks/useOrganisationPermissions.ts +9 -11
  209. package/src/hooks/useOrganisations.ts +13 -7
  210. package/src/hooks/useQueryCache.ts +0 -1
  211. package/src/hooks/useSessionDraft.ts +380 -0
  212. package/src/hooks/useSessionRestoration.ts +3 -1
  213. package/src/icons/index.ts +27 -0
  214. package/src/index.ts +16 -1
  215. package/src/providers/OrganisationProvider.tsx +23 -14
  216. package/src/providers/services/EventServiceProvider.tsx +1 -24
  217. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  218. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
  219. package/src/rbac/README.md +20 -20
  220. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  221. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  222. package/src/rbac/adapters.tsx +7 -295
  223. package/src/rbac/api.test.ts +44 -56
  224. package/src/rbac/api.ts +10 -17
  225. package/src/rbac/cache-invalidation.ts +0 -1
  226. package/src/rbac/compliance/index.ts +10 -0
  227. package/src/rbac/compliance/pattern-detector.ts +553 -0
  228. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  229. package/src/rbac/components/AccessDenied.tsx +150 -0
  230. package/src/rbac/components/NavigationGuard.tsx +12 -20
  231. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  232. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  233. package/src/rbac/components/index.ts +3 -41
  234. package/src/rbac/eslint-rules.js +1 -1
  235. package/src/rbac/hooks/index.ts +0 -3
  236. package/src/rbac/hooks/permissions/index.ts +0 -3
  237. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  238. package/src/rbac/hooks/usePermissions.ts +0 -3
  239. package/src/rbac/hooks/useRBAC.test.ts +21 -3
  240. package/src/rbac/hooks/useRBAC.ts +4 -3
  241. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  242. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  243. package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
  244. package/src/rbac/hooks/useResourcePermissions.ts +182 -63
  245. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  246. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  247. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  248. package/src/rbac/index.ts +7 -9
  249. package/src/rbac/permissions.ts +17 -17
  250. package/src/rbac/utils/contextValidator.ts +45 -7
  251. package/src/services/AuthService.ts +132 -23
  252. package/src/services/EventService.ts +4 -97
  253. package/src/services/InactivityService.ts +155 -58
  254. package/src/services/OrganisationService.ts +7 -44
  255. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  256. package/src/services/base/BaseService.ts +0 -3
  257. package/src/styles/core.css +4 -0
  258. package/src/types/database.generated.ts +4733 -3809
  259. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  260. package/src/utils/context/organisationContext.test.ts +13 -28
  261. package/src/utils/context/organisationContext.ts +21 -52
  262. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  263. package/src/utils/file-reference/index.ts +39 -15
  264. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  265. package/src/utils/formatting/formatTime.test.ts +3 -2
  266. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  267. package/src/utils/index.ts +4 -1
  268. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  269. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  270. package/src/utils/persistence/keyDerivation.ts +304 -0
  271. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  272. package/src/utils/security/secureStorage.ts +5 -5
  273. package/src/utils/storage/helpers.ts +3 -3
  274. package/src/utils/supabase/createBaseClient.ts +147 -0
  275. package/src/utils/timezone/timezone.test.ts +1 -2
  276. package/src/utils/timezone/timezone.ts +1 -1
  277. package/src/utils/validation/csrf.ts +4 -4
  278. package/cursor-rules/CHANGELOG.md +0 -119
  279. package/cursor-rules/README.md +0 -192
  280. package/dist/DataTable-E7YQZD7D.js +0 -175
  281. package/dist/DataTable-E7YQZD7D.js.map +0 -1
  282. package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
  283. package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
  284. package/dist/api-6LVZTHDS.js +0 -52
  285. package/dist/api-6LVZTHDS.js.map +0 -1
  286. package/dist/audit-V53FV5AG.js +0 -17
  287. package/dist/audit-V53FV5AG.js.map +0 -1
  288. package/dist/chunk-36LVWXB2.js +0 -227
  289. package/dist/chunk-36LVWXB2.js.map +0 -1
  290. package/dist/chunk-3LPHPB62.js.map +0 -1
  291. package/dist/chunk-5DRSZLL2.js.map +0 -1
  292. package/dist/chunk-5EC5MEWX.js.map +0 -1
  293. package/dist/chunk-63FOKYGO.js.map +0 -1
  294. package/dist/chunk-6SOIHG6Z.js.map +0 -1
  295. package/dist/chunk-7JPAB3T5.js.map +0 -1
  296. package/dist/chunk-ATKZM7RX.js +0 -2053
  297. package/dist/chunk-ATKZM7RX.js.map +0 -1
  298. package/dist/chunk-AVMLPIM7.js.map +0 -1
  299. package/dist/chunk-DGUM43GV.js.map +0 -1
  300. package/dist/chunk-E66EQZE6.js.map +0 -1
  301. package/dist/chunk-FFQEQTNW.js.map +0 -1
  302. package/dist/chunk-FMUCXFII.js.map +0 -1
  303. package/dist/chunk-G37KK66H.js.map +0 -1
  304. package/dist/chunk-I6DAQMWX.js.map +0 -1
  305. package/dist/chunk-J36DSWQK.js.map +0 -1
  306. package/dist/chunk-KQCRWDSA.js +0 -1
  307. package/dist/chunk-KQCRWDSA.js.map +0 -1
  308. package/dist/chunk-L4OXEN46.js.map +0 -1
  309. package/dist/chunk-LMC26NLJ.js +0 -84
  310. package/dist/chunk-LMC26NLJ.js.map +0 -1
  311. package/dist/chunk-M43Y4SSO.js.map +0 -1
  312. package/dist/chunk-M7MPQISP.js.map +0 -1
  313. package/dist/chunk-NN6WWZ5U.js.map +0 -1
  314. package/dist/chunk-OEWDTMG7.js.map +0 -1
  315. package/dist/chunk-PWLANIRT.js.map +0 -1
  316. package/dist/chunk-QXHPKYJV.js.map +0 -1
  317. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  318. package/dist/chunk-YKRAFF5K.js.map +0 -1
  319. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  320. package/dist/components.js.map +0 -1
  321. package/dist/contextValidator-OOPCLPZW.js +0 -9
  322. package/dist/contextValidator-OOPCLPZW.js.map +0 -1
  323. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  324. package/dist/hooks.js.map +0 -1
  325. package/dist/index.js.map +0 -1
  326. package/dist/providers.js.map +0 -1
  327. package/dist/rbac/eslint-rules.js.map +0 -1
  328. package/dist/rbac/index.js.map +0 -1
  329. package/dist/styles/index.js.map +0 -1
  330. package/dist/theming/runtime.js.map +0 -1
  331. package/dist/types.js.map +0 -1
  332. package/dist/utils.js.map +0 -1
  333. package/docs/standards/01-architecture-standard.md +0 -44
  334. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  335. package/docs/standards/03-component-standard.md +0 -32
  336. package/docs/standards/05-security-standard.md +0 -44
  337. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  338. package/docs/standards/pace-core-compliance.md +0 -432
  339. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  340. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  341. package/scripts/audit/core/checks/bundle.cjs +0 -142
  342. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  343. package/scripts/audit/core/checks/config.cjs +0 -54
  344. package/scripts/audit/core/checks/coverage.cjs +0 -84
  345. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  346. package/scripts/audit/core/checks/documentation.cjs +0 -268
  347. package/scripts/audit/core/checks/environment.cjs +0 -116
  348. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  349. package/scripts/audit/core/checks/forms.cjs +0 -172
  350. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  351. package/scripts/audit/core/checks/hooks.cjs +0 -334
  352. package/scripts/audit/core/checks/imports.cjs +0 -244
  353. package/scripts/audit/core/checks/performance.cjs +0 -325
  354. package/scripts/audit/core/checks/routes.cjs +0 -117
  355. package/scripts/audit/core/checks/state.cjs +0 -130
  356. package/scripts/audit/core/checks/structure.cjs +0 -65
  357. package/scripts/audit/core/checks/style.cjs +0 -584
  358. package/scripts/audit/core/checks/testing.cjs +0 -122
  359. package/scripts/audit/core/checks/typescript.cjs +0 -61
  360. package/scripts/audit/core/scanner.cjs +0 -199
  361. package/scripts/audit/core/utils.cjs +0 -137
  362. package/scripts/audit/reporters/console.cjs +0 -151
  363. package/scripts/audit/reporters/json.cjs +0 -54
  364. package/scripts/audit/reporters/markdown.cjs +0 -124
  365. package/scripts/audit-consuming-app.cjs +0 -86
  366. package/src/eslint-rules/pace-core-compliance.cjs +0 -510
  367. package/src/eslint-rules/pace-core-compliance.js +0 -638
  368. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  369. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  370. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  371. package/src/rbac/components/NavigationProvider.tsx +0 -345
  372. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  373. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  374. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  375. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  376. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  377. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  378. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  379. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  380. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  381. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  382. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  383. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  384. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  385. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  386. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  387. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Testing Patterns Check Module
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Checks/Testing
7
- *
8
- * Checks for:
9
- * - Missing test files for critical components
10
- * - Test files without assertions
11
- * - Missing integration tests for RBAC flows
12
- */
13
-
14
- const fs = require('fs');
15
- const path = require('path');
16
- const { getRelativePath } = require('../utils.cjs');
17
-
18
- const testingCheck = {
19
- name: 'testing',
20
- description: 'Testing patterns (test coverage, missing tests)',
21
- severity: 'suggestion',
22
-
23
- async run(context) {
24
- const { projectRoot, files } = context;
25
- const issues = [];
26
- const warnings = [];
27
- const suggestions = [];
28
-
29
- if (!files || files.length === 0) {
30
- return { issues, warnings, suggestions };
31
- }
32
-
33
- // Find all component files
34
- const componentFiles = files.filter(f => f.match(/\.(tsx|jsx)$/) &&
35
- !f.includes('.test.') &&
36
- !f.includes('.spec.'));
37
-
38
- // Find all test files
39
- const testFiles = files.filter(f => f.match(/\.(test|spec)\.(ts|tsx|js|jsx)$/));
40
- const testFileSet = new Set(testFiles.map(f => {
41
- // Get base name without .test/.spec
42
- return f.replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, '');
43
- }));
44
-
45
- // Check for components without tests
46
- componentFiles.forEach(componentFile => {
47
- const baseName = componentFile.replace(/\.(tsx|jsx)$/, '');
48
- const hasTest = testFileSet.has(baseName + '.ts') ||
49
- testFileSet.has(baseName + '.tsx') ||
50
- testFileSet.has(baseName + '.js') ||
51
- testFileSet.has(baseName + '.jsx');
52
-
53
- if (!hasTest) {
54
- const relativePath = getRelativePath(componentFile, projectRoot);
55
-
56
- // Check if it's a critical component (has RBAC, auth, or is exported)
57
- const content = fs.readFileSync(componentFile, 'utf8');
58
- const isCritical = content.includes('usePermissions') ||
59
- content.includes('useCan') ||
60
- content.includes('PagePermissionGuard') ||
61
- content.includes('useUnifiedAuth') ||
62
- content.match(/^export\s+(default\s+)?(function|const|class)\s+\w+/m);
63
-
64
- if (isCritical) {
65
- warnings.push({
66
- type: 'missing-test',
67
- file: relativePath,
68
- message: 'Critical component missing test file',
69
- recommendation: `Create a test file for this component: ${path.basename(baseName)}.test.tsx`
70
- });
71
- } else {
72
- suggestions.push({
73
- type: 'missing-test',
74
- file: relativePath,
75
- message: 'Component missing test file',
76
- recommendation: `Consider adding tests for this component: ${path.basename(baseName)}.test.tsx`
77
- });
78
- }
79
- }
80
- });
81
-
82
- // Check test files for assertions
83
- testFiles.forEach(testFile => {
84
- try {
85
- const content = fs.readFileSync(testFile, 'utf8');
86
- const relativePath = getRelativePath(testFile, projectRoot);
87
-
88
- // Check for test assertions
89
- const hasAssertions = /expect\(|assert\(|toBe\(|toEqual\(|toMatch\(/.test(content);
90
-
91
- if (!hasAssertions) {
92
- warnings.push({
93
- type: 'test-without-assertions',
94
- file: relativePath,
95
- message: 'Test file has no assertions',
96
- recommendation: 'Add assertions to verify test behavior'
97
- });
98
- }
99
-
100
- // Check for RBAC-related tests
101
- if (content.includes('usePermissions') || content.includes('useCan') || content.includes('PagePermissionGuard')) {
102
- const hasRBACTests = /permission|rbac|access|role/i.test(content);
103
- if (!hasRBACTests) {
104
- suggestions.push({
105
- type: 'missing-rbac-tests',
106
- file: relativePath,
107
- message: 'Component uses RBAC but tests may not cover permission scenarios',
108
- recommendation: 'Add tests for different permission levels and access scenarios'
109
- });
110
- }
111
- }
112
-
113
- } catch (error) {
114
- // Skip files with errors
115
- }
116
- });
117
-
118
- return { issues, warnings, suggestions };
119
- }
120
- };
121
-
122
- module.exports = testingCheck;
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * TypeScript Config Check Module
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Checks/TypeScript
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- const typescriptCheck = {
13
- name: 'typescript',
14
- description: 'TypeScript configuration checks (strict mode, etc.)',
15
- severity: 'error',
16
-
17
- async run(context) {
18
- const { projectRoot } = context;
19
- const issues = [];
20
- const warnings = [];
21
-
22
- const tsconfigPath = path.join(projectRoot, 'tsconfig.json');
23
- if (!fs.existsSync(tsconfigPath)) {
24
- return { issues, warnings, suggestions: [] };
25
- }
26
-
27
- try {
28
- const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
29
- const compilerOptions = tsconfig.compilerOptions || {};
30
-
31
- if (!compilerOptions.strict) {
32
- issues.push({
33
- type: 'typescript-config',
34
- file: 'tsconfig.json',
35
- message: 'TypeScript strict mode is not enabled',
36
- recommendation: 'Set "strict": true in tsconfig.json'
37
- });
38
- }
39
-
40
- if (compilerOptions.noImplicitAny === false) {
41
- issues.push({
42
- type: 'typescript-config',
43
- file: 'tsconfig.json',
44
- message: 'noImplicitAny is disabled',
45
- recommendation: 'Set "noImplicitAny": true in tsconfig.json'
46
- });
47
- }
48
- } catch (error) {
49
- warnings.push({
50
- type: 'typescript-config',
51
- file: 'tsconfig.json',
52
- message: `Could not parse tsconfig.json: ${error.message}`,
53
- recommendation: 'Check that tsconfig.json is valid JSON'
54
- });
55
- }
56
-
57
- return { issues, warnings, suggestions: [] };
58
- }
59
- };
60
-
61
- module.exports = typescriptCheck;
@@ -1,199 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Core scanning engine that orchestrates all checks
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Scanner
7
- */
8
-
9
- const { findProjectRoot, findSourceFiles } = require('./utils.cjs');
10
-
11
- /**
12
- * Scanner class that orchestrates check execution
13
- */
14
- class Scanner {
15
- constructor(projectRoot = null) {
16
- this.projectRoot = projectRoot || findProjectRoot();
17
- this.checks = [];
18
- this.context = {
19
- projectRoot: this.projectRoot,
20
- files: null,
21
- packageJson: null,
22
- manifest: null
23
- };
24
- }
25
-
26
- /**
27
- * Register a check module
28
- * @param {Object} check - Check module with { name, description, run, severity }
29
- */
30
- registerCheck(check) {
31
- if (!check.name || !check.run || typeof check.run !== 'function') {
32
- throw new Error('Check must have name and run function');
33
- }
34
- this.checks.push(check);
35
- }
36
-
37
- /**
38
- * Register multiple checks
39
- * @param {Object[]} checks - Array of check modules
40
- */
41
- registerChecks(checks) {
42
- checks.forEach(check => this.registerCheck(check));
43
- }
44
-
45
- /**
46
- * Initialize scanner context
47
- * @param {Object} options - Options for initialization
48
- */
49
- async initialize(options = {}) {
50
- const { manifest = null, skipFileDiscovery = false } = options;
51
-
52
- this.context.manifest = manifest;
53
-
54
- if (!skipFileDiscovery) {
55
- this.context.files = findSourceFiles(this.projectRoot);
56
- }
57
-
58
- // Load package.json if needed
59
- if (!this.context.packageJson) {
60
- const { getPackageInfo } = require('./utils.cjs');
61
- this.context.packageJson = getPackageInfo(this.projectRoot);
62
- }
63
- }
64
-
65
- /**
66
- * Run all registered checks
67
- * @param {Object} options - Options for running checks
68
- * @returns {Promise<Object>} Aggregated results from all checks
69
- */
70
- async run(options = {}) {
71
- const {
72
- checkNames = null, // Run only specific checks
73
- excludeChecks = [], // Exclude specific checks
74
- parallel = false // Run checks in parallel
75
- } = options;
76
-
77
- // Filter checks to run
78
- let checksToRun = this.checks;
79
- if (checkNames && Array.isArray(checkNames)) {
80
- checksToRun = this.checks.filter(check => checkNames.includes(check.name));
81
- }
82
- if (excludeChecks && Array.isArray(excludeChecks)) {
83
- checksToRun = checksToRun.filter(check => !excludeChecks.includes(check.name));
84
- }
85
-
86
- const results = {
87
- checks: {},
88
- summary: {
89
- total: 0,
90
- errors: 0,
91
- warnings: 0,
92
- suggestions: 0,
93
- passed: 0
94
- },
95
- metadata: {
96
- projectRoot: this.projectRoot,
97
- filesScanned: this.context.files?.length || 0,
98
- checksRun: checksToRun.length,
99
- timestamp: new Date().toISOString()
100
- }
101
- };
102
-
103
- // Run checks
104
- if (parallel) {
105
- const checkPromises = checksToRun.map(check => this.runCheck(check));
106
- const checkResults = await Promise.all(checkPromises);
107
- checkResults.forEach((result, index) => {
108
- const check = checksToRun[index];
109
- results.checks[check.name] = result;
110
- this.updateSummary(results.summary, result);
111
- });
112
- } else {
113
- for (const check of checksToRun) {
114
- const result = await this.runCheck(check);
115
- results.checks[check.name] = result;
116
- this.updateSummary(results.summary, result);
117
- }
118
- }
119
-
120
- return results;
121
- }
122
-
123
- /**
124
- * Run a single check
125
- * @param {Object} check - Check module to run
126
- * @returns {Promise<Object>} Check result
127
- */
128
- async runCheck(check) {
129
- const startTime = Date.now();
130
- try {
131
- const result = await check.run(this.context);
132
- const duration = Date.now() - startTime;
133
-
134
- return {
135
- name: check.name,
136
- description: check.description || '',
137
- severity: check.severity || 'warning',
138
- status: 'completed',
139
- duration,
140
- ...result
141
- };
142
- } catch (error) {
143
- const duration = Date.now() - startTime;
144
- return {
145
- name: check.name,
146
- description: check.description || '',
147
- severity: check.severity || 'warning',
148
- status: 'error',
149
- error: error.message,
150
- duration,
151
- issues: [],
152
- warnings: [],
153
- suggestions: []
154
- };
155
- }
156
- }
157
-
158
- /**
159
- * Update summary statistics
160
- * @param {Object} summary - Summary object to update
161
- * @param {Object} result - Check result
162
- */
163
- updateSummary(summary, result) {
164
- summary.total++;
165
-
166
- if (result.status === 'error') {
167
- summary.errors++;
168
- return;
169
- }
170
-
171
- const issues = result.issues || [];
172
- const warnings = result.warnings || [];
173
- const suggestions = result.suggestions || [];
174
-
175
- if (issues.length > 0) {
176
- summary.errors += issues.length;
177
- }
178
- if (warnings.length > 0) {
179
- summary.warnings += warnings.length;
180
- }
181
- if (suggestions.length > 0) {
182
- summary.suggestions += suggestions.length;
183
- }
184
-
185
- if (issues.length === 0 && warnings.length === 0 && suggestions.length === 0) {
186
- summary.passed++;
187
- }
188
- }
189
-
190
- /**
191
- * Get context for checks
192
- * @returns {Object} Scanner context
193
- */
194
- getContext() {
195
- return this.context;
196
- }
197
- }
198
-
199
- module.exports = Scanner;
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Shared utilities for audit system
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Utils
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- // ANSI color codes for terminal output
13
- const colors = {
14
- reset: '\x1b[0m',
15
- green: '\x1b[32m',
16
- yellow: '\x1b[33m',
17
- blue: '\x1b[34m',
18
- cyan: '\x1b[36m',
19
- bold: '\x1b[1m',
20
- red: '\x1b[31m'
21
- };
22
-
23
- /**
24
- * Find project root by looking for package.json
25
- * @param {string} startDir - Directory to start searching from
26
- * @returns {string} Project root directory path
27
- */
28
- function findProjectRoot(startDir = process.cwd()) {
29
- let current = path.resolve(startDir);
30
- while (current !== path.dirname(current)) {
31
- if (fs.existsSync(path.join(current, 'package.json'))) {
32
- return current;
33
- }
34
- current = path.dirname(current);
35
- }
36
- return startDir;
37
- }
38
-
39
- /**
40
- * Recursively find all source files in a directory
41
- * @param {string} dir - Directory to search
42
- * @param {string[]} fileList - Accumulated file list (for recursion)
43
- * @returns {string[]} Array of file paths
44
- */
45
- function findSourceFiles(dir, fileList = []) {
46
- const ignoreDirs = ['node_modules', 'dist', 'build', '.next', 'coverage', '__tests__', '__mocks__'];
47
- const ignoreFiles = /\.(test|spec)\.(ts|tsx|js|jsx)$/;
48
- const sourceExtensions = /\.(ts|tsx|js|jsx)$/;
49
-
50
- try {
51
- const items = fs.readdirSync(dir);
52
-
53
- items.forEach(item => {
54
- const fullPath = path.join(dir, item);
55
- const stat = fs.statSync(fullPath);
56
-
57
- if (stat.isDirectory()) {
58
- // Skip Edge Functions directory - they run in Deno, not React
59
- if (item === 'functions' && dir.includes('supabase')) {
60
- return;
61
- }
62
- if (!ignoreDirs.includes(item) && !item.startsWith('.')) {
63
- findSourceFiles(fullPath, fileList);
64
- }
65
- } else if (stat.isFile()) {
66
- if (sourceExtensions.test(item) && !ignoreFiles.test(item)) {
67
- fileList.push(fullPath);
68
- }
69
- }
70
- });
71
- } catch (error) {
72
- // Skip directories we can't read
73
- }
74
-
75
- return fileList;
76
- }
77
-
78
- /**
79
- * Get package.json info
80
- * @param {string} projectRoot - Project root directory
81
- * @returns {Object|null} Parsed package.json or null
82
- */
83
- function getPackageInfo(projectRoot) {
84
- const packagePath = path.join(projectRoot, 'package.json');
85
- if (!fs.existsSync(packagePath)) {
86
- return null;
87
- }
88
- try {
89
- return JSON.parse(fs.readFileSync(packagePath, 'utf8'));
90
- } catch (error) {
91
- return null;
92
- }
93
- }
94
-
95
- /**
96
- * Get pace-core version from package.json
97
- * @param {Object} packageJson - Parsed package.json
98
- * @returns {string} Version string or 'unknown'
99
- */
100
- function getPaceCoreVersion(packageJson) {
101
- if (!packageJson) return 'unknown';
102
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
103
- return deps['@jmruthers/pace-core'] || 'unknown';
104
- }
105
-
106
- /**
107
- * Get line number for a match in content
108
- * @param {string} content - File content
109
- * @param {string|number} match - Match string or index
110
- * @returns {number} Line number (1-indexed)
111
- */
112
- function getLineNumber(content, match) {
113
- const index = typeof match === 'string' ? content.indexOf(match) : match;
114
- if (index === -1) return 1;
115
- const lines = content.substring(0, index).split('\n');
116
- return lines.length;
117
- }
118
-
119
- /**
120
- * Get relative path from project root
121
- * @param {string} filePath - Absolute file path
122
- * @param {string} projectRoot - Project root directory
123
- * @returns {string} Relative path
124
- */
125
- function getRelativePath(filePath, projectRoot) {
126
- return path.relative(projectRoot, filePath);
127
- }
128
-
129
- module.exports = {
130
- colors,
131
- findProjectRoot,
132
- findSourceFiles,
133
- getPackageInfo,
134
- getPaceCoreVersion,
135
- getLineNumber,
136
- getRelativePath
137
- };
@@ -1,151 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Console Reporter
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Reporters/Console
7
- *
8
- * Formats audit results for terminal output with color coding
9
- */
10
-
11
- const { colors } = require('../core/utils.cjs');
12
-
13
- /**
14
- * Format check results for console output
15
- */
16
- function formatCheckResult(checkName, result) {
17
- const { issues = [], warnings = [], suggestions = [] } = result;
18
- const total = issues.length + warnings.length + suggestions.length;
19
-
20
- if (total === 0) {
21
- return `${colors.green}✓${colors.reset} ${checkName}: No issues found`;
22
- }
23
-
24
- const parts = [];
25
- if (issues.length > 0) {
26
- parts.push(`${colors.red}${issues.length} error${issues.length !== 1 ? 's' : ''}${colors.reset}`);
27
- }
28
- if (warnings.length > 0) {
29
- parts.push(`${colors.yellow}${warnings.length} warning${warnings.length !== 1 ? 's' : ''}${colors.reset}`);
30
- }
31
- if (suggestions.length > 0) {
32
- parts.push(`${colors.blue}${suggestions.length} suggestion${suggestions.length !== 1 ? 's' : ''}${colors.reset}`);
33
- }
34
-
35
- return `${colors.red}✗${colors.reset} ${checkName}: ${parts.join(', ')}`;
36
- }
37
-
38
- /**
39
- * Format a single issue/warning/suggestion for console
40
- */
41
- function formatItem(item, type) {
42
- const icon = type === 'issue' ? `${colors.red}•${colors.reset}` :
43
- type === 'warning' ? `${colors.yellow}⚠${colors.reset}` :
44
- `${colors.blue}💡${colors.reset}`;
45
-
46
- const fileInfo = item.line ? `${colors.yellow}${item.file}:${item.line}${colors.reset}` : `${colors.yellow}${item.file}${colors.reset}`;
47
-
48
- let output = ` ${icon} ${fileInfo}\n`;
49
- output += ` ${item.message || item.type}\n`;
50
-
51
- if (item.recommendation) {
52
- output += ` ${colors.green}Recommendation:${colors.reset} ${item.recommendation}\n`;
53
- }
54
-
55
- return output + '\n';
56
- }
57
-
58
- /**
59
- * Generate console report
60
- */
61
- function generateReport(results, options = {}) {
62
- const { verbose = false } = options;
63
-
64
- console.log(`\n${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
65
- console.log(`${colors.bold}${colors.cyan} pace-core Audit Report${colors.reset}`);
66
- console.log(`${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
67
-
68
- // Summary
69
- const summary = results.summary || {};
70
- console.log(`${colors.bold}Summary:${colors.reset}`);
71
- console.log(` ${colors.red}Errors:${colors.reset} ${summary.errors || 0}`);
72
- console.log(` ${colors.yellow}Warnings:${colors.reset} ${summary.warnings || 0}`);
73
- console.log(` ${colors.blue}Suggestions:${colors.reset} ${summary.suggestions || 0}`);
74
- console.log(` ${colors.green}Passed:${colors.reset} ${summary.passed || 0}`);
75
- console.log(` ${colors.cyan}Total Checks:${colors.reset} ${summary.total || 0}\n`);
76
-
77
- // Check results
78
- if (results.checks) {
79
- console.log(`${colors.bold}Check Results:${colors.reset}\n`);
80
- Object.entries(results.checks).forEach(([checkName, result]) => {
81
- console.log(formatCheckResult(checkName, result));
82
-
83
- if (verbose && (result.issues?.length > 0 || result.warnings?.length > 0 || result.suggestions?.length > 0)) {
84
- if (result.issues?.length > 0) {
85
- console.log(`\n ${colors.red}${colors.bold}Errors:${colors.reset}\n`);
86
- result.issues.forEach(issue => {
87
- console.log(formatItem(issue, 'issue'));
88
- });
89
- }
90
-
91
- if (result.warnings?.length > 0) {
92
- console.log(` ${colors.yellow}${colors.bold}Warnings:${colors.reset}\n`);
93
- result.warnings.forEach(warning => {
94
- console.log(formatItem(warning, 'warning'));
95
- });
96
- }
97
-
98
- if (result.suggestions?.length > 0) {
99
- console.log(` ${colors.blue}${colors.bold}Suggestions:${colors.reset}\n`);
100
- result.suggestions.forEach(suggestion => {
101
- console.log(formatItem(suggestion, 'suggestion'));
102
- });
103
- }
104
- }
105
- });
106
- }
107
-
108
- // Compliance violations (if present)
109
- if (results.checks?.compliance?.violations) {
110
- const violations = results.checks.compliance.violations;
111
- console.log(`\n${colors.bold}${colors.cyan}Compliance Details:${colors.reset}\n`);
112
-
113
- // Format compliance violations similar to original report
114
- formatComplianceViolations(violations);
115
- }
116
-
117
- console.log('');
118
- }
119
-
120
- /**
121
- * Format compliance violations for console (similar to original format)
122
- */
123
- function formatComplianceViolations(violations) {
124
- const totalRestricted = violations.restrictedImports?.length || 0;
125
- const totalDuplicates =
126
- (violations.duplicateComponents?.length || 0) +
127
- (violations.duplicateHooks?.length || 0) +
128
- (violations.duplicateUtils?.length || 0);
129
-
130
- if (totalRestricted > 0) {
131
- console.log(`${colors.red}${colors.bold}❌ Restricted Imports: ${totalRestricted}${colors.reset}\n`);
132
- violations.restrictedImports.forEach(({ module, reason, file, line }) => {
133
- console.log(` ${colors.red}•${colors.reset} ${colors.yellow}${file}:${line}${colors.reset}`);
134
- console.log(` Import: ${colors.cyan}${module}${colors.reset}`);
135
- console.log(` ${colors.yellow}Reason:${colors.reset} ${reason}\n`);
136
- });
137
- }
138
-
139
- if (totalDuplicates > 0) {
140
- console.log(`${colors.red}${colors.bold}❌ Duplicates: ${totalDuplicates}${colors.reset}\n`);
141
- // Format duplicates...
142
- }
143
-
144
- // Format other violation types...
145
- }
146
-
147
- module.exports = {
148
- generateReport,
149
- formatCheckResult,
150
- formatItem
151
- };