@jmruthers/pace-core 0.6.5 → 0.6.7

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 (473) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/audit-tool/00-dependencies.cjs +394 -0
  4. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  5. package/audit-tool/audits/02-project-structure.cjs +255 -0
  6. package/audit-tool/audits/03-architecture.cjs +196 -0
  7. package/audit-tool/audits/04-code-quality.cjs +149 -0
  8. package/audit-tool/audits/05-styling.cjs +224 -0
  9. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  10. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  11. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  12. package/audit-tool/audits/09-operations.cjs +208 -0
  13. package/audit-tool/index.cjs +291 -0
  14. package/audit-tool/utils/code-utils.cjs +218 -0
  15. package/audit-tool/utils/file-utils.cjs +230 -0
  16. package/audit-tool/utils/report-utils.cjs +241 -0
  17. package/core-usage-manifest.json +93 -0
  18. package/cursor-rules/00-standards-overview.mdc +156 -0
  19. package/cursor-rules/01-pace-core-compliance.mdc +586 -0
  20. package/cursor-rules/02-project-structure.mdc +42 -4
  21. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
  22. package/cursor-rules/04-code-quality.mdc +419 -0
  23. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
  24. package/cursor-rules/06-security-rbac.mdc +518 -0
  25. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  26. package/cursor-rules/08-testing-documentation.mdc +324 -0
  27. package/cursor-rules/09-operations.mdc +365 -0
  28. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  29. package/dist/DataTable-7PMH7XN7.js +15 -0
  30. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  31. package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
  32. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  33. package/dist/api-Y4MQWOFW.js +4 -0
  34. package/dist/audit-MYQXYZFU.js +3 -0
  35. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  36. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  37. package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
  38. package/dist/chunk-6F3IILHI.js +62 -0
  39. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  40. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  41. package/dist/{chunk-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
  42. package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
  43. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  44. package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
  45. package/dist/chunk-C7NSAPTL.js +1 -0
  46. package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
  47. package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
  48. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  49. package/dist/chunk-GHYHJTYV.js +994 -0
  50. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  51. package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
  52. package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
  53. package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
  54. package/dist/chunk-MBADTM7L.js +64 -0
  55. package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
  56. package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
  57. package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
  58. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  59. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  60. package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
  61. package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
  62. package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
  63. package/dist/components.d.ts +7 -5
  64. package/dist/components.js +46 -257
  65. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  66. package/dist/eslint-rules/index.cjs +35 -0
  67. package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
  68. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  69. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  70. package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
  71. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  72. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  73. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  74. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  75. package/dist/hooks.d.ts +6 -6
  76. package/dist/hooks.js +62 -172
  77. package/dist/icons/index.d.ts +1 -0
  78. package/dist/icons/index.js +1 -0
  79. package/dist/index.d.ts +12 -11
  80. package/dist/index.js +67 -660
  81. package/dist/providers.d.ts +2 -2
  82. package/dist/providers.js +8 -35
  83. package/dist/rbac/eslint-rules.d.ts +46 -44
  84. package/dist/rbac/eslint-rules.js +7 -4
  85. package/dist/rbac/index.d.ts +109 -586
  86. package/dist/rbac/index.js +14 -207
  87. package/dist/styles/index.js +2 -12
  88. package/dist/theming/runtime.d.ts +14 -1
  89. package/dist/theming/runtime.js +3 -19
  90. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  91. package/dist/{types-CkbwOr4Y.d.ts → types-DXstZpNI.d.ts} +4 -17
  92. package/dist/types-t9H8qKRw.d.ts +55 -0
  93. package/dist/types.d.ts +1 -1
  94. package/dist/types.js +7 -94
  95. package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
  96. package/dist/utils.d.ts +24 -117
  97. package/dist/utils.js +54 -392
  98. package/docs/README.md +17 -7
  99. package/docs/api/README.md +4 -402
  100. package/docs/api/modules.md +301 -871
  101. package/docs/api-reference/components.md +21 -21
  102. package/docs/api-reference/deprecated.md +31 -6
  103. package/docs/api-reference/hooks.md +80 -80
  104. package/docs/api-reference/rpc-functions.md +78 -3
  105. package/docs/api-reference/types.md +1 -1
  106. package/docs/api-reference/utilities.md +1 -1
  107. package/docs/architecture/README.md +1 -1
  108. package/docs/core-concepts/events.md +3 -3
  109. package/docs/core-concepts/organisations.md +6 -6
  110. package/docs/core-concepts/permissions.md +6 -6
  111. package/docs/documentation-index.md +12 -18
  112. package/docs/getting-started/cursor-rules.md +3 -23
  113. package/docs/getting-started/dependencies.md +650 -0
  114. package/docs/getting-started/documentation-index.md +1 -1
  115. package/docs/getting-started/examples/README.md +4 -4
  116. package/docs/getting-started/examples/full-featured-app.md +1 -1
  117. package/docs/getting-started/faq.md +2 -2
  118. package/docs/getting-started/installation-guide.md +20 -7
  119. package/docs/getting-started/quick-reference.md +4 -4
  120. package/docs/getting-started/quick-start.md +23 -12
  121. package/docs/implementation-guides/authentication.md +15 -15
  122. package/docs/implementation-guides/component-styling.md +1 -1
  123. package/docs/implementation-guides/data-tables.md +126 -33
  124. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  125. package/docs/implementation-guides/dynamic-colors.md +3 -3
  126. package/docs/implementation-guides/file-upload-storage.md +2 -2
  127. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  128. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  129. package/docs/implementation-guides/large-datasets.md +3 -2
  130. package/docs/implementation-guides/organisation-security.md +2 -2
  131. package/docs/implementation-guides/performance.md +2 -2
  132. package/docs/implementation-guides/permission-enforcement.md +5 -1
  133. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  134. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  135. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  136. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  137. package/docs/rbac/README.md +17 -8
  138. package/docs/rbac/advanced-patterns.md +6 -6
  139. package/docs/rbac/api-reference.md +20 -20
  140. package/docs/rbac/edge-functions-guide.md +376 -0
  141. package/docs/rbac/event-based-apps.md +3 -3
  142. package/docs/rbac/examples.md +41 -41
  143. package/docs/rbac/getting-started.md +37 -37
  144. package/docs/rbac/performance.md +1 -1
  145. package/docs/rbac/quick-start.md +52 -52
  146. package/docs/rbac/secure-client-protection.md +1 -35
  147. package/docs/rbac/troubleshooting.md +1 -1
  148. package/docs/security/README.md +5 -5
  149. package/docs/standards/0-standards-overview.md +220 -0
  150. package/docs/standards/1-pace-core-compliance-standards.md +986 -0
  151. package/docs/standards/2-project-structure-standards.md +949 -0
  152. package/docs/standards/3-architecture-standards.md +606 -0
  153. package/docs/standards/4-code-quality-standards.md +728 -0
  154. package/docs/standards/5-styling-standards.md +348 -0
  155. package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
  156. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  157. package/docs/standards/8-testing-documentation-standards.md +401 -0
  158. package/docs/standards/9-operations-standards.md +1102 -0
  159. package/docs/standards/README.md +185 -57
  160. package/docs/troubleshooting/README.md +4 -4
  161. package/docs/troubleshooting/common-issues.md +2 -2
  162. package/docs/troubleshooting/debugging.md +9 -9
  163. package/docs/troubleshooting/migration.md +4 -4
  164. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  165. package/eslint-config-pace-core.cjs +33 -6
  166. package/package.json +35 -23
  167. package/scripts/install-cursor-rules.cjs +25 -6
  168. package/scripts/install-eslint-config.cjs +284 -0
  169. package/src/__tests__/fixtures/supabase.ts +1 -1
  170. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
  171. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  172. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  173. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  174. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
  175. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  176. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  177. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  178. package/src/__tests__/public-recipe-view.test.ts +38 -9
  179. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  180. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  181. package/src/__tests__/templates/component.test.template.tsx +18 -15
  182. package/src/components/Button/Button.tsx +5 -1
  183. package/src/components/Calendar/Calendar.tsx +201 -47
  184. package/src/components/ContextSelector/ContextSelector.tsx +106 -119
  185. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  186. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  187. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  188. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  189. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  190. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  191. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  192. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  193. package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
  194. package/src/components/DataTable/components/EditFields.tsx +23 -3
  195. package/src/components/DataTable/components/EditableRow.tsx +12 -9
  196. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  197. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  198. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  199. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  200. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  201. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  202. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  203. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  204. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  205. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  206. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  207. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  208. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  209. package/src/components/DataTable/components/index.ts +2 -1
  210. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  212. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  213. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  214. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  215. package/src/components/DataTable/types.ts +5 -18
  216. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  217. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  218. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  219. package/src/components/DateTimeField/DateTimeField.tsx +10 -9
  220. package/src/components/Dialog/Dialog.test.tsx +128 -104
  221. package/src/components/Dialog/Dialog.tsx +742 -24
  222. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  223. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
  224. package/src/components/FileDisplay/FileDisplay.tsx +23 -17
  225. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  226. package/src/components/FileUpload/FileUpload.tsx +112 -130
  227. package/src/components/Form/Form.test.tsx +6 -8
  228. package/src/components/Form/Form.tsx +365 -4
  229. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  230. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  231. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  232. package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
  233. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  234. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  235. package/src/components/Progress/Progress.tsx +2 -4
  236. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  237. package/src/components/Select/Select.tsx +109 -98
  238. package/src/components/Select/types.ts +4 -1
  239. package/src/components/UserMenu/UserMenu.tsx +9 -6
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
  242. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  243. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  244. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  245. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  246. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  247. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  248. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  249. package/src/hooks/public/usePublicEvent.ts +67 -195
  250. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  251. package/src/hooks/public/usePublicEventLogo.ts +24 -14
  252. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  253. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  254. package/src/hooks/useAppConfig.ts +28 -26
  255. package/src/hooks/useEventTheme.test.ts +217 -239
  256. package/src/hooks/useEventTheme.ts +16 -28
  257. package/src/hooks/useFileDisplay.ts +2 -2
  258. package/src/hooks/useOrganisationPermissions.ts +5 -7
  259. package/src/hooks/useQueryCache.ts +0 -1
  260. package/src/hooks/useSessionDraft.ts +380 -0
  261. package/src/hooks/useSessionRestoration.ts +3 -1
  262. package/src/icons/index.ts +27 -0
  263. package/src/index.ts +5 -0
  264. package/src/providers/OrganisationProvider.tsx +23 -14
  265. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  266. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  267. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  268. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  269. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  270. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  271. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  272. package/src/providers/services/EventServiceProvider.tsx +1 -24
  273. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  274. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  275. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
  276. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  277. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  278. package/src/rbac/adapters.tsx +7 -295
  279. package/src/rbac/api.test.ts +44 -56
  280. package/src/rbac/api.ts +10 -17
  281. package/src/rbac/cache-invalidation.ts +0 -1
  282. package/src/rbac/compliance/index.ts +10 -0
  283. package/src/rbac/compliance/pattern-detector.ts +553 -0
  284. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  285. package/src/rbac/components/AccessDenied.tsx +150 -0
  286. package/src/rbac/components/NavigationGuard.tsx +12 -20
  287. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  289. package/src/rbac/components/index.ts +3 -41
  290. package/src/rbac/eslint-rules.js +1 -1
  291. package/src/rbac/hooks/index.ts +0 -3
  292. package/src/rbac/hooks/permissions/index.ts +0 -3
  293. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  294. package/src/rbac/hooks/usePermissions.ts +0 -3
  295. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  296. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  297. package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
  298. package/src/rbac/hooks/useResourcePermissions.ts +139 -48
  299. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  300. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  301. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  302. package/src/rbac/index.ts +7 -9
  303. package/src/rbac/utils/contextValidator.ts +9 -7
  304. package/src/services/AuthService.ts +130 -18
  305. package/src/services/EventService.ts +4 -97
  306. package/src/services/InactivityService.ts +16 -0
  307. package/src/services/OrganisationService.ts +7 -44
  308. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  309. package/src/services/base/BaseService.ts +0 -3
  310. package/src/styles/core.css +7 -0
  311. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  312. package/src/theming/parseEventColours.ts +22 -10
  313. package/src/types/database.generated.ts +4733 -3809
  314. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  315. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  316. package/src/utils/context/organisationContext.test.ts +13 -28
  317. package/src/utils/context/organisationContext.ts +21 -52
  318. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  319. package/src/utils/file-reference/index.ts +39 -15
  320. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  321. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  322. package/src/utils/index.ts +4 -1
  323. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  324. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  325. package/src/utils/persistence/keyDerivation.ts +304 -0
  326. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  327. package/src/utils/security/secureStorage.ts +5 -5
  328. package/src/utils/storage/README.md +1 -1
  329. package/src/utils/storage/helpers.ts +3 -3
  330. package/src/utils/supabase/createBaseClient.ts +147 -0
  331. package/src/utils/timezone/timezone.test.ts +1 -2
  332. package/src/utils/timezone/timezone.ts +1 -1
  333. package/src/utils/validation/csrf.ts +4 -4
  334. package/cursor-rules/00-pace-core-compliance.mdc +0 -331
  335. package/cursor-rules/01-standards-compliance.mdc +0 -244
  336. package/cursor-rules/04-testing-standards.mdc +0 -268
  337. package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
  338. package/cursor-rules/06-code-quality.mdc +0 -309
  339. package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
  340. package/cursor-rules/CHANGELOG.md +0 -119
  341. package/cursor-rules/README.md +0 -192
  342. package/dist/DataTable-AOVNCPTX.js +0 -175
  343. package/dist/DataTable-AOVNCPTX.js.map +0 -1
  344. package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
  345. package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
  346. package/dist/api-O6HTBX5Y.js +0 -52
  347. package/dist/api-O6HTBX5Y.js.map +0 -1
  348. package/dist/audit-V53FV5AG.js +0 -17
  349. package/dist/audit-V53FV5AG.js.map +0 -1
  350. package/dist/chunk-5DRSZLL2.js.map +0 -1
  351. package/dist/chunk-63FOKYGO.js.map +0 -1
  352. package/dist/chunk-6COVEUS7.js.map +0 -1
  353. package/dist/chunk-AFVQODI2.js +0 -263
  354. package/dist/chunk-AFVQODI2.js.map +0 -1
  355. package/dist/chunk-DGUM43GV.js.map +0 -1
  356. package/dist/chunk-E66EQZE6.js.map +0 -1
  357. package/dist/chunk-EFN2EIMK.js.map +0 -1
  358. package/dist/chunk-FFQEQTNW.js.map +0 -1
  359. package/dist/chunk-FMUCXFII.js.map +0 -1
  360. package/dist/chunk-G37KK66H.js.map +0 -1
  361. package/dist/chunk-G7QEZTYQ.js +0 -2053
  362. package/dist/chunk-G7QEZTYQ.js.map +0 -1
  363. package/dist/chunk-HU2C6SSC.js.map +0 -1
  364. package/dist/chunk-IHB5DR3H.js.map +0 -1
  365. package/dist/chunk-IVOFDYWT.js.map +0 -1
  366. package/dist/chunk-J36DSWQK.js.map +0 -1
  367. package/dist/chunk-JGRYX5UX.js.map +0 -1
  368. package/dist/chunk-KQCRWDSA.js +0 -1
  369. package/dist/chunk-KQCRWDSA.js.map +0 -1
  370. package/dist/chunk-L4OXEN46.js.map +0 -1
  371. package/dist/chunk-LMC26NLJ.js +0 -84
  372. package/dist/chunk-LMC26NLJ.js.map +0 -1
  373. package/dist/chunk-M43Y4SSO.js.map +0 -1
  374. package/dist/chunk-M7MPQISP.js.map +0 -1
  375. package/dist/chunk-NTM7ZSB6.js.map +0 -1
  376. package/dist/chunk-PWLANIRT.js.map +0 -1
  377. package/dist/chunk-QXHPKYJV.js.map +0 -1
  378. package/dist/chunk-RGAWHO7N.js.map +0 -1
  379. package/dist/chunk-UPPMRMYG.js.map +0 -1
  380. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  381. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  382. package/dist/components.js.map +0 -1
  383. package/dist/contextValidator-5OGXSPKS.js +0 -9
  384. package/dist/contextValidator-5OGXSPKS.js.map +0 -1
  385. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  386. package/dist/hooks.js.map +0 -1
  387. package/dist/index.js.map +0 -1
  388. package/dist/providers.js.map +0 -1
  389. package/dist/rbac/eslint-rules.js.map +0 -1
  390. package/dist/rbac/index.js.map +0 -1
  391. package/dist/styles/index.js.map +0 -1
  392. package/dist/theming/runtime.js.map +0 -1
  393. package/dist/types.js.map +0 -1
  394. package/dist/utils.js.map +0 -1
  395. package/docs/best-practices/README.md +0 -472
  396. package/docs/best-practices/accessibility.md +0 -601
  397. package/docs/best-practices/common-patterns.md +0 -516
  398. package/docs/best-practices/deployment.md +0 -1103
  399. package/docs/best-practices/performance.md +0 -1328
  400. package/docs/best-practices/security.md +0 -940
  401. package/docs/best-practices/testing.md +0 -1034
  402. package/docs/rbac/compliance/compliance-guide.md +0 -544
  403. package/docs/standards/01-architecture-standard.md +0 -44
  404. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  405. package/docs/standards/03-component-standard.md +0 -32
  406. package/docs/standards/04-code-style-standard.md +0 -32
  407. package/docs/standards/05-security-standard.md +0 -44
  408. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  409. package/docs/standards/pace-core-compliance.md +0 -432
  410. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  411. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  412. package/scripts/audit/core/checks/bundle.cjs +0 -142
  413. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  414. package/scripts/audit/core/checks/config.cjs +0 -54
  415. package/scripts/audit/core/checks/coverage.cjs +0 -84
  416. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  417. package/scripts/audit/core/checks/documentation.cjs +0 -268
  418. package/scripts/audit/core/checks/environment.cjs +0 -116
  419. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  420. package/scripts/audit/core/checks/forms.cjs +0 -172
  421. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  422. package/scripts/audit/core/checks/hooks.cjs +0 -334
  423. package/scripts/audit/core/checks/imports.cjs +0 -244
  424. package/scripts/audit/core/checks/performance.cjs +0 -325
  425. package/scripts/audit/core/checks/routes.cjs +0 -117
  426. package/scripts/audit/core/checks/state.cjs +0 -130
  427. package/scripts/audit/core/checks/structure.cjs +0 -65
  428. package/scripts/audit/core/checks/style.cjs +0 -584
  429. package/scripts/audit/core/checks/testing.cjs +0 -122
  430. package/scripts/audit/core/checks/typescript.cjs +0 -61
  431. package/scripts/audit/core/scanner.cjs +0 -199
  432. package/scripts/audit/core/utils.cjs +0 -137
  433. package/scripts/audit/index.cjs +0 -223
  434. package/scripts/audit/reporters/console.cjs +0 -151
  435. package/scripts/audit/reporters/json.cjs +0 -54
  436. package/scripts/audit/reporters/markdown.cjs +0 -124
  437. package/scripts/audit-consuming-app.cjs +0 -86
  438. package/src/components/DataTable/components/DataTableBody.tsx +0 -454
  439. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  440. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  441. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  442. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  443. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  444. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  445. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  446. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  447. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  448. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  449. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  450. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  451. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  452. package/src/components/DataTable/utils/debugTools.ts +0 -514
  453. package/src/eslint-rules/pace-core-compliance.js +0 -638
  454. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  455. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  456. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  457. package/src/rbac/components/NavigationProvider.tsx +0 -345
  458. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  459. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  460. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  461. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  462. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  463. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  464. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  465. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  466. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  467. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  468. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  469. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  470. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  471. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  472. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  473. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -1,1103 +0,0 @@
1
- ---
2
- lastUpdated: 2025-11-18T17:00:00+11:00
3
- version: 0.5.181
4
- reviewedBy: documentation-standards-audit
5
- ---
6
-
7
- # Deployment Best Practices
8
-
9
- Proper deployment is crucial for production success. This guide provides comprehensive deployment strategies and best practices for `@jmruthers/pace-core` applications.
10
-
11
- ## Overview
12
-
13
- Deployment in `@jmruthers/pace-core` covers multiple environments:
14
-
15
- - **Development**: Local development and testing
16
- - **Staging**: Pre-production testing and validation
17
- - **Production**: Live application with high availability
18
- - **CI/CD**: Automated build and deployment pipelines
19
-
20
- ## Environment Configuration
21
-
22
- ### 1. Environment Variables
23
-
24
- ```typescript
25
- // .env.local (development)
26
- VITE_SUPABASE_URL=http://localhost:54321
27
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
28
- VITE_SUPABASE_PUBLISHABLE_KEY=your-local-publishable-key
29
- VITE_APP_ENV=development
30
- VITE_DEBUG=true
31
-
32
- // .env.staging
33
- VITE_SUPABASE_URL=https://your-project.supabase.co
34
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
35
- VITE_SUPABASE_PUBLISHABLE_KEY=your-staging-publishable-key
36
- VITE_APP_ENV=staging
37
- VITE_DEBUG=false
38
-
39
- // .env.production
40
- VITE_SUPABASE_URL=https://your-project.supabase.co
41
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
42
- VITE_SUPABASE_PUBLISHABLE_KEY=your-production-publishable-key
43
- VITE_APP_ENV=production
44
- VITE_DEBUG=false
45
- ```
46
-
47
- ### 2. Environment-Specific Configuration
48
-
49
- ```typescript
50
- // config/environment.ts
51
- export const getEnvironmentConfig = () => {
52
- const env = import.meta.env.VITE_APP_ENV || 'development';
53
-
54
- const configs = {
55
- development: {
56
- apiUrl: 'http://localhost:54321',
57
- debug: true,
58
- logLevel: 'debug',
59
- features: {
60
- analytics: false,
61
- monitoring: false,
62
- },
63
- },
64
- staging: {
65
- apiUrl: 'https://your-staging-project.supabase.co',
66
- debug: false,
67
- logLevel: 'info',
68
- features: {
69
- analytics: true,
70
- monitoring: true,
71
- },
72
- },
73
- production: {
74
- apiUrl: 'https://your-production-project.supabase.co',
75
- debug: false,
76
- logLevel: 'warn',
77
- features: {
78
- analytics: true,
79
- monitoring: true,
80
- },
81
- },
82
- };
83
-
84
- return configs[env] || configs.development;
85
- };
86
- ```
87
-
88
- ### 3. Feature Flags
89
-
90
- ```typescript
91
- // utils/featureFlags.ts
92
- export const FEATURE_FLAGS = {
93
- NEW_UI: process.env.VITE_FEATURE_NEW_UI === 'true',
94
- BETA_FEATURES: process.env.VITE_FEATURE_BETA === 'true',
95
- ANALYTICS: process.env.VITE_FEATURE_ANALYTICS === 'true',
96
- DEBUG_MODE: process.env.VITE_DEBUG === 'true',
97
- };
98
-
99
- export const isFeatureEnabled = (feature: keyof typeof FEATURE_FLAGS) => {
100
- return FEATURE_FLAGS[feature];
101
- };
102
-
103
- // Usage in components
104
- function MyComponent() {
105
- if (isFeatureEnabled('NEW_UI')) {
106
- return <NewUIComponent />;
107
- }
108
- return <LegacyComponent />;
109
- }
110
- ```
111
-
112
- ## Build Optimization
113
-
114
- ### 1. Production Build Configuration
115
-
116
- ```typescript
117
- // vite.config.ts
118
- import { defineConfig } from 'vite';
119
- import react from '@vitejs/plugin-react';
120
- import { resolve } from 'path';
121
-
122
- export default defineConfig({
123
- plugins: [react()],
124
- build: {
125
- target: 'es2015',
126
- outDir: 'dist',
127
- sourcemap: false, // Disable in production
128
- minify: 'terser',
129
- rollupOptions: {
130
- output: {
131
- manualChunks: {
132
- vendor: ['react', 'react-dom'],
133
- paceCore: ['@jmruthers/pace-core'],
134
- supabase: ['@supabase/supabase-js'],
135
- },
136
- },
137
- },
138
- terserOptions: {
139
- compress: {
140
- drop_console: true, // Remove console.log in production
141
- drop_debugger: true,
142
- },
143
- },
144
- },
145
- define: {
146
- __DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
147
- },
148
- });
149
- ```
150
-
151
- ### 2. Bundle Analysis
152
-
153
- ```typescript
154
- // scripts/analyze-bundle.js
155
- import { build } from 'vite';
156
- import { visualizer } from 'rollup-plugin-visualizer';
157
-
158
- export default defineConfig({
159
- plugins: [
160
- visualizer({
161
- filename: 'dist/stats.html',
162
- open: true,
163
- gzipSize: true,
164
- brotliSize: true,
165
- }),
166
- ],
167
- build: {
168
- rollupOptions: {
169
- output: {
170
- manualChunks: {
171
- vendor: ['react', 'react-dom'],
172
- paceCore: ['@jmruthers/pace-core'],
173
- supabase: ['@supabase/supabase-js'],
174
- utils: ['lodash', 'date-fns'],
175
- },
176
- },
177
- },
178
- },
179
- });
180
- ```
181
-
182
- ### 3. Code Splitting
183
-
184
- ```typescript
185
- // Lazy load components based on routes
186
- import { lazy, Suspense } from 'react';
187
-
188
- const AdminDashboard = lazy(() => import('./AdminDashboard'));
189
- const UserDashboard = lazy(() => import('./UserDashboard'));
190
- const Analytics = lazy(() => import('./Analytics'));
191
-
192
- import { useCan } from '@jmruthers/pace-core/rbac';
193
-
194
- function App() {
195
- const { user, selectedOrganisationId } = useUnifiedAuth();
196
- const { can: canViewAdmin } = useCan(
197
- user?.id || '',
198
- { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
199
- 'read:page.admin'
200
- );
201
-
202
- return (
203
- <Suspense fallback={<LoadingSpinner />}>
204
- {canViewAdmin ? (
205
- <AdminDashboard />
206
- ) : (
207
- <UserDashboard />
208
- )}
209
- {canViewAdmin && (
210
- <Suspense fallback={<div>Loading analytics...</div>}>
211
- <Analytics />
212
- </Suspense>
213
- )}
214
- </Suspense>
215
- );
216
- }
217
- ```
218
-
219
- ## CI/CD Pipeline
220
-
221
- ### 1. GitHub Actions Workflow
222
-
223
- ```yaml
224
- # .github/workflows/deploy.yml
225
- name: Deploy
226
-
227
- on:
228
- push:
229
- branches: [main, develop]
230
- pull_request:
231
- branches: [main]
232
-
233
- jobs:
234
- test:
235
- runs-on: ubuntu-latest
236
- steps:
237
- - uses: actions/checkout@v3
238
-
239
- - name: Setup Node.js
240
- uses: actions/setup-node@v3
241
- with:
242
- node-version: '18'
243
- cache: 'npm'
244
-
245
- - name: Install dependencies
246
- run: npm ci
247
-
248
- - name: Run tests
249
- run: npm test
250
-
251
- - name: Run type check
252
- run: npm run type-check
253
-
254
- - name: Run linting
255
- run: npm run lint
256
-
257
- build:
258
- needs: test
259
- runs-on: ubuntu-latest
260
- if: github.ref == 'refs/heads/main'
261
- steps:
262
- - uses: actions/checkout@v3
263
-
264
- - name: Setup Node.js
265
- uses: actions/setup-node@v3
266
- with:
267
- node-version: '18'
268
- cache: 'npm'
269
-
270
- - name: Install dependencies
271
- run: npm ci
272
-
273
- - name: Build application
274
- run: npm run build
275
- env:
276
- VITE_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
277
- VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.SUPABASE_PUBLISHABLE_KEY }}
278
- VITE_APP_ENV: production
279
-
280
- - name: Upload build artifacts
281
- uses: actions/upload-artifact@v3
282
- with:
283
- name: build-files
284
- path: dist/
285
-
286
- deploy-staging:
287
- needs: build
288
- runs-on: ubuntu-latest
289
- if: github.ref == 'refs/heads/develop'
290
- steps:
291
- - uses: actions/checkout@v3
292
-
293
- - name: Download build artifacts
294
- uses: actions/download-artifact@v3
295
- with:
296
- name: build-files
297
- path: dist/
298
-
299
- - name: Deploy to staging
300
- run: |
301
- # Deploy to staging environment
302
- # This could be Vercel, Netlify, AWS, etc.
303
- echo "Deploying to staging..."
304
-
305
- deploy-production:
306
- needs: build
307
- runs-on: ubuntu-latest
308
- if: github.ref == 'refs/heads/main'
309
- environment: production
310
- steps:
311
- - uses: actions/checkout@v3
312
-
313
- - name: Download build artifacts
314
- uses: actions/download-artifact@v3
315
- with:
316
- name: build-files
317
- path: dist/
318
-
319
- - name: Deploy to production
320
- run: |
321
- # Deploy to production environment
322
- echo "Deploying to production..."
323
- ```
324
-
325
- ### 2. Environment-Specific Deployments
326
-
327
- ```yaml
328
- # .github/workflows/deploy-staging.yml
329
- name: Deploy to Staging
330
-
331
- on:
332
- push:
333
- branches: [develop]
334
-
335
- jobs:
336
- deploy:
337
- runs-on: ubuntu-latest
338
- steps:
339
- - uses: actions/checkout@v3
340
-
341
- - name: Setup Node.js
342
- uses: actions/setup-node@v3
343
- with:
344
- node-version: '18'
345
- cache: 'npm'
346
-
347
- - name: Install dependencies
348
- run: npm ci
349
-
350
- - name: Run tests
351
- run: npm test
352
-
353
- - name: Build for staging
354
- run: npm run build:staging
355
- env:
356
- VITE_SUPABASE_URL: ${{ secrets.STAGING_SUPABASE_URL }}
357
- VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.STAGING_SUPABASE_PUBLISHABLE_KEY }}
358
- VITE_APP_ENV: staging
359
-
360
- - name: Deploy to Vercel (Staging)
361
- uses: amondnet/vercel-action@v25
362
- with:
363
- vercel-token: ${{ secrets.VERCEL_TOKEN }}
364
- vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
365
- vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
366
- vercel-args: '--prod'
367
- ```
368
-
369
- ### 3. Automated Testing in CI
370
-
371
- ```yaml
372
- # .github/workflows/test.yml
373
- name: Test
374
-
375
- on:
376
- push:
377
- branches: [main, develop]
378
- pull_request:
379
- branches: [main]
380
-
381
- jobs:
382
- test:
383
- runs-on: ubuntu-latest
384
- strategy:
385
- matrix:
386
- node-version: [16, 18, 20]
387
-
388
- steps:
389
- - uses: actions/checkout@v3
390
-
391
- - name: Setup Node.js ${{ matrix.node-version }}
392
- uses: actions/setup-node@v3
393
- with:
394
- node-version: ${{ matrix.node-version }}
395
- cache: 'npm'
396
-
397
- - name: Install dependencies
398
- run: npm ci
399
-
400
- - name: Run unit tests
401
- run: npm run test:unit
402
-
403
- - name: Run integration tests
404
- run: npm run test:integration
405
-
406
- - name: Run E2E tests
407
- run: npm run test:e2e
408
-
409
- - name: Upload coverage
410
- uses: codecov/codecov-action@v3
411
- with:
412
- file: ./coverage/lcov.info
413
- ```
414
-
415
- ## Deployment Platforms
416
-
417
- ### 1. Vercel Deployment
418
-
419
- ```json
420
- // vercel.json
421
- {
422
- "version": 2,
423
- "builds": [
424
- {
425
- "src": "package.json",
426
- "use": "@vercel/static-build",
427
- "config": {
428
- "distDir": "dist"
429
- }
430
- }
431
- ],
432
- "routes": [
433
- {
434
- "src": "/api/(.*)",
435
- "dest": "/api/$1"
436
- },
437
- {
438
- "src": "/(.*)",
439
- "dest": "/index.html"
440
- }
441
- ],
442
- "env": {
443
- "VITE_SUPABASE_URL": "@supabase-url",
444
- "VITE_SUPABASE_PUBLISHABLE_KEY": "@supabase-publishable-key"
445
- }
446
- }
447
- ```
448
-
449
- ### 2. Netlify Deployment
450
-
451
- ```toml
452
- # netlify.toml
453
- [build]
454
- command = "npm run build"
455
- publish = "dist"
456
-
457
- [build.environment]
458
- VITE_SUPABASE_URL = "https://your-project.supabase.co"
459
- VITE_APP_ENV = "production"
460
-
461
- [[redirects]]
462
- from = "/*"
463
- to = "/index.html"
464
- status = 200
465
-
466
- [[headers]]
467
- for = "/*"
468
- [headers.values]
469
- X-Frame-Options = "DENY"
470
- X-XSS-Protection = "1; mode=block"
471
- X-Content-Type-Options = "nosniff"
472
- Referrer-Policy = "strict-origin-when-cross-origin"
473
- ```
474
-
475
- ### 3. AWS S3 + CloudFront
476
-
477
- ```typescript
478
- // scripts/deploy-aws.js
479
- import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
480
- import { CloudFrontClient, CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
481
- import { readdir, readFile } from 'fs/promises';
482
- import { join } from 'path';
483
-
484
- const s3Client = new S3Client({ region: 'us-east-1' });
485
- const cloudFrontClient = new CloudFrontClient({ region: 'us-east-1' });
486
-
487
- async function deployToS3() {
488
- const bucketName = process.env.AWS_S3_BUCKET;
489
- const distributionId = process.env.AWS_CLOUDFRONT_DISTRIBUTION_ID;
490
-
491
- // Upload build files to S3
492
- const buildDir = join(process.cwd(), 'dist');
493
- const files = await readdir(buildDir, { recursive: true });
494
-
495
- for (const file of files) {
496
- const filePath = join(buildDir, file);
497
- const fileContent = await readFile(filePath);
498
-
499
- await s3Client.send(new PutObjectCommand({
500
- Bucket: bucketName,
501
- Key: file,
502
- Body: fileContent,
503
- ContentType: getContentType(file),
504
- CacheControl: getCacheControl(file),
505
- }));
506
- }
507
-
508
- // Invalidate CloudFront cache
509
- await cloudFrontClient.send(new CreateInvalidationCommand({
510
- DistributionId: distributionId,
511
- InvalidationBatch: {
512
- Paths: {
513
- Quantity: 1,
514
- Items: ['/*'],
515
- },
516
- CallerReference: Date.now().toString(),
517
- },
518
- }));
519
- }
520
-
521
- function getContentType(filename) {
522
- if (filename.endsWith('.html')) return 'text/html';
523
- if (filename.endsWith('.css')) return 'text/css';
524
- if (filename.endsWith('.js')) return 'application/javascript';
525
- if (filename.endsWith('.json')) return 'application/json';
526
- return 'application/octet-stream';
527
- }
528
-
529
- function getCacheControl(filename) {
530
- if (filename.endsWith('.html')) return 'no-cache';
531
- if (filename.endsWith('.css') || filename.endsWith('.js')) return 'public, max-age=31536000';
532
- return 'public, max-age=86400';
533
- }
534
-
535
- deployToS3().catch(console.error);
536
- ```
537
-
538
- ## Security Deployment
539
-
540
- ### 1. Security Headers
541
-
542
- ```typescript
543
- // server/security-headers.js
544
- export const securityHeaders = {
545
- 'Content-Security-Policy': [
546
- "default-src 'self'",
547
- "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
548
- "style-src 'self' 'unsafe-inline'",
549
- "img-src 'self' data: https:",
550
- "font-src 'self'",
551
- "connect-src 'self' https://*.supabase.co",
552
- "frame-ancestors 'none'",
553
- ].join('; '),
554
-
555
- 'X-Frame-Options': 'DENY',
556
- 'X-Content-Type-Options': 'nosniff',
557
- 'X-XSS-Protection': '1; mode=block',
558
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
559
- 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
560
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
561
- };
562
- ```
563
-
564
- ### 2. Environment Variable Security
565
-
566
- ```bash
567
- # .env.example (template for required variables)
568
- VITE_SUPABASE_URL=
569
- VITE_SUPABASE_PUBLISHABLE_KEY=
570
- VITE_APP_ENV=development
571
- VITE_DEBUG=false
572
-
573
- # .env.production (actual production values - never commit)
574
- VITE_SUPABASE_URL=https://your-project.supabase.co
575
- VITE_SUPABASE_PUBLISHABLE_KEY=your-production-publishable-key
576
- VITE_APP_ENV=production
577
- VITE_DEBUG=false
578
- ```
579
-
580
- ### 3. SSL/TLS Configuration
581
-
582
- ```nginx
583
- # nginx.conf
584
- server {
585
- listen 443 ssl http2;
586
- server_name your-domain.com;
587
-
588
- ssl_certificate /path/to/certificate.crt;
589
- ssl_certificate_key /path/to/private.key;
590
-
591
- ssl_protocols TLSv1.2 TLSv1.3;
592
- ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
593
- ssl_prefer_server_ciphers off;
594
-
595
- ssl_session_cache shared:SSL:10m;
596
- ssl_session_timeout 10m;
597
-
598
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
599
- add_header X-Frame-Options DENY always;
600
- add_header X-Content-Type-Options nosniff always;
601
- add_header X-XSS-Protection "1; mode=block" always;
602
-
603
- location / {
604
- root /var/www/html;
605
- try_files $uri $uri/ /index.html;
606
- }
607
- }
608
- ```
609
-
610
- ## Monitoring and Logging
611
-
612
- ### 1. Application Monitoring
613
-
614
- ```typescript
615
- // utils/monitoring.ts
616
- export class ApplicationMonitor {
617
- private static instance: ApplicationMonitor;
618
- private metrics: Map<string, number> = new Map();
619
- private errors: Error[] = [];
620
-
621
- static getInstance(): ApplicationMonitor {
622
- if (!ApplicationMonitor.instance) {
623
- ApplicationMonitor.instance = new ApplicationMonitor();
624
- }
625
- return ApplicationMonitor.instance;
626
- }
627
-
628
- trackEvent(eventName: string, properties?: Record<string, any>) {
629
- // Send to analytics service
630
- if (typeof gtag !== 'undefined') {
631
- gtag('event', eventName, properties);
632
- }
633
-
634
- // Track custom metrics
635
- this.metrics.set(eventName, (this.metrics.get(eventName) || 0) + 1);
636
- }
637
-
638
- trackError(error: Error, context?: Record<string, any>) {
639
- this.errors.push(error);
640
-
641
- // Send to error tracking service
642
- if (typeof Sentry !== 'undefined') {
643
- Sentry.captureException(error, {
644
- extra: context,
645
- });
646
- }
647
- }
648
-
649
- trackPerformance(metric: string, value: number) {
650
- // Send to performance monitoring service
651
- if (typeof gtag !== 'undefined') {
652
- gtag('event', 'timing_complete', {
653
- name: metric,
654
- value: value,
655
- });
656
- }
657
- }
658
-
659
- getMetrics() {
660
- return Object.fromEntries(this.metrics);
661
- }
662
-
663
- getErrors() {
664
- return this.errors;
665
- }
666
- }
667
-
668
- // Usage
669
- const monitor = ApplicationMonitor.getInstance();
670
- monitor.trackEvent('user_login');
671
- monitor.trackError(new Error('API call failed'), { endpoint: '/api/events' });
672
- monitor.trackPerformance('page_load', 1200);
673
- ```
674
-
675
- ### 2. Health Checks
676
-
677
- ```typescript
678
- // api/health.ts
679
- export const healthCheck = async (req: Request, res: Response) => {
680
- try {
681
- // Check database connection
682
- const { data, error } = await supabase
683
- .from('health_check')
684
- .select('*')
685
- .limit(1);
686
-
687
- if (error) {
688
- return res.status(503).json({
689
- status: 'unhealthy',
690
- database: 'down',
691
- timestamp: new Date().toISOString(),
692
- });
693
- }
694
-
695
- // Check external services
696
- const externalServices = await Promise.allSettled([
697
- fetch('https://api.supabase.co/health'),
698
- fetch('https://your-analytics-service.com/health'),
699
- ]);
700
-
701
- const healthy = externalServices.every(result =>
702
- result.status === 'fulfilled' && result.value.ok
703
- );
704
-
705
- return res.status(healthy ? 200 : 503).json({
706
- status: healthy ? 'healthy' : 'degraded',
707
- database: 'up',
708
- external_services: externalServices.map(result =>
709
- result.status === 'fulfilled' && result.value.ok ? 'up' : 'down'
710
- ),
711
- timestamp: new Date().toISOString(),
712
- });
713
- } catch (error) {
714
- return res.status(503).json({
715
- status: 'unhealthy',
716
- error: error.message,
717
- timestamp: new Date().toISOString(),
718
- });
719
- }
720
- };
721
- ```
722
-
723
- ### 3. Logging Configuration
724
-
725
- ```typescript
726
- // utils/logger.ts
727
- export enum LogLevel {
728
- DEBUG = 0,
729
- INFO = 1,
730
- WARN = 2,
731
- ERROR = 3,
732
- }
733
-
734
- export class Logger {
735
- private level: LogLevel;
736
- private context: string;
737
-
738
- constructor(context: string, level: LogLevel = LogLevel.INFO) {
739
- this.context = context;
740
- this.level = level;
741
- }
742
-
743
- debug(message: string, data?: any) {
744
- if (this.level <= LogLevel.DEBUG) {
745
- console.debug(`[DEBUG] ${this.context}: ${message}`, data);
746
- }
747
- }
748
-
749
- info(message: string, data?: any) {
750
- if (this.level <= LogLevel.INFO) {
751
- console.info(`[INFO] ${this.context}: ${message}`, data);
752
- }
753
- }
754
-
755
- warn(message: string, data?: any) {
756
- if (this.level <= LogLevel.WARN) {
757
- console.warn(`[WARN] ${this.context}: ${message}`, data);
758
- }
759
- }
760
-
761
- error(message: string, error?: Error, data?: any) {
762
- if (this.level <= LogLevel.ERROR) {
763
- console.error(`[ERROR] ${this.context}: ${message}`, error, data);
764
- }
765
- }
766
- }
767
-
768
- // Usage
769
- const logger = new Logger('AuthService', LogLevel.DEBUG);
770
- logger.info('User logged in', { userId: '123' });
771
- logger.error('Authentication failed', new Error('Invalid credentials'));
772
- ```
773
-
774
- ## Rollback Strategy
775
-
776
- ### 1. Blue-Green Deployment
777
-
778
- ```yaml
779
- # .github/workflows/blue-green-deploy.yml
780
- name: Blue-Green Deployment
781
-
782
- on:
783
- push:
784
- branches: [main]
785
-
786
- jobs:
787
- deploy-blue:
788
- runs-on: ubuntu-latest
789
- steps:
790
- - name: Deploy to Blue Environment
791
- run: |
792
- # Deploy to blue environment
793
- echo "Deploying to blue environment..."
794
-
795
- - name: Run Health Checks
796
- run: |
797
- # Run health checks on blue environment
798
- curl -f https://blue.your-domain.com/health
799
-
800
- - name: Switch Traffic to Blue
801
- run: |
802
- # Switch traffic from green to blue
803
- echo "Switching traffic to blue environment..."
804
-
805
- rollback:
806
- runs-on: ubuntu-latest
807
- if: failure()
808
- steps:
809
- - name: Rollback to Green
810
- run: |
811
- # Rollback to green environment
812
- echo "Rolling back to green environment..."
813
- ```
814
-
815
- ### 2. Canary Deployment
816
-
817
- ```typescript
818
- // utils/canary-deployment.ts
819
- export class CanaryDeployment {
820
- private static instance: CanaryDeployment;
821
- private currentVersion: string;
822
- private canaryPercentage: number = 0;
823
-
824
- static getInstance(): CanaryDeployment {
825
- if (!CanaryDeployment.instance) {
826
- CanaryDeployment.instance = new CanaryDeployment();
827
- }
828
- return CanaryDeployment.instance;
829
- }
830
-
831
- setCanaryPercentage(percentage: number) {
832
- this.canaryPercentage = Math.max(0, Math.min(100, percentage));
833
- }
834
-
835
- shouldServeCanary(userId: string): boolean {
836
- // Deterministic canary selection based on user ID
837
- const hash = this.hashString(userId);
838
- return (hash % 100) < this.canaryPercentage;
839
- }
840
-
841
- private hashString(str: string): number {
842
- let hash = 0;
843
- for (let i = 0; i < str.length; i++) {
844
- const char = str.charCodeAt(i);
845
- hash = ((hash << 5) - hash) + char;
846
- hash = hash & hash; // Convert to 32-bit integer
847
- }
848
- return Math.abs(hash);
849
- }
850
-
851
- trackCanaryMetrics(userId: string, version: string, success: boolean) {
852
- // Track canary metrics
853
- const monitor = ApplicationMonitor.getInstance();
854
- monitor.trackEvent('canary_request', {
855
- userId,
856
- version,
857
- success,
858
- percentage: this.canaryPercentage,
859
- });
860
- }
861
- }
862
-
863
- // Usage
864
- const canary = CanaryDeployment.getInstance();
865
- canary.setCanaryPercentage(10); // 10% of users get canary
866
-
867
- if (canary.shouldServeCanary(user.id)) {
868
- // Serve canary version
869
- canary.trackCanaryMetrics(user.id, 'v2.0.0', true);
870
- }
871
- ```
872
-
873
- ## Performance Monitoring
874
-
875
- ### 1. Core Web Vitals
876
-
877
- ```typescript
878
- // utils/web-vitals.ts
879
- import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
880
-
881
- export const trackWebVitals = () => {
882
- getCLS(console.log);
883
- getFID(console.log);
884
- getFCP(console.log);
885
- getLCP(console.log);
886
- getTTFB(console.log);
887
- };
888
-
889
- export const trackCustomMetrics = () => {
890
- // Track custom performance metrics
891
- const observer = new PerformanceObserver((list) => {
892
- for (const entry of list.getEntries()) {
893
- const monitor = ApplicationMonitor.getInstance();
894
- monitor.trackPerformance(entry.name, entry.startTime);
895
- }
896
- });
897
-
898
- observer.observe({ entryTypes: ['measure', 'navigation'] });
899
- };
900
-
901
- // Track component render times
902
- export const trackComponentPerformance = (componentName: string) => {
903
- const startTime = performance.now();
904
-
905
- return () => {
906
- const endTime = performance.now();
907
- const renderTime = endTime - startTime;
908
-
909
- const monitor = ApplicationMonitor.getInstance();
910
- monitor.trackPerformance(`${componentName}_render`, renderTime);
911
- };
912
- };
913
- ```
914
-
915
- ### 2. Error Tracking
916
-
917
- ```typescript
918
- // utils/error-tracking.ts
919
- import * as Sentry from '@sentry/react';
920
-
921
- export const initializeErrorTracking = () => {
922
- if (process.env.VITE_APP_ENV === 'production') {
923
- Sentry.init({
924
- dsn: process.env.VITE_SENTRY_DSN,
925
- environment: process.env.VITE_APP_ENV,
926
- integrations: [
927
- new Sentry.BrowserTracing(),
928
- new Sentry.Replay(),
929
- ],
930
- tracesSampleRate: 0.1,
931
- replaysSessionSampleRate: 0.1,
932
- replaysOnErrorSampleRate: 1.0,
933
- });
934
- }
935
- };
936
-
937
- export const captureError = (error: Error, context?: Record<string, any>) => {
938
- if (process.env.VITE_APP_ENV === 'production') {
939
- Sentry.captureException(error, {
940
- extra: context,
941
- });
942
- } else {
943
- console.error('Error captured:', error, context);
944
- }
945
- };
946
- ```
947
-
948
- ## Deployment Checklist
949
-
950
- ### Pre-Deployment Checklist
951
-
952
- - [ ] All tests passing
953
- - [ ] Code review completed
954
- - [ ] Security scan passed
955
- - [ ] Performance benchmarks met
956
- - [ ] Environment variables configured
957
- - [ ] Database migrations applied
958
- - [ ] SSL certificates valid
959
- - [ ] Monitoring configured
960
- - [ ] Rollback plan ready
961
- - [ ] Team notified
962
-
963
- ### Deployment Checklist
964
-
965
- - [ ] Deploy to staging environment
966
- - [ ] Run smoke tests
967
- - [ ] Verify all features work
968
- - [ ] Check performance metrics
969
- - [ ] Validate security headers
970
- - [ ] Test error handling
971
- - [ ] Verify monitoring alerts
972
- - [ ] Deploy to production
973
- - [ ] Monitor application health
974
- - [ ] Verify user experience
975
-
976
- ### Post-Deployment Checklist
977
-
978
- - [ ] Monitor error rates
979
- - [ ] Check performance metrics
980
- - [ ] Verify user feedback
981
- - [ ] Monitor resource usage
982
- - [ ] Check security alerts
983
- - [ ] Validate analytics data
984
- - [ ] Update documentation
985
- - [ ] Archive old deployment
986
- - [ ] Clean up temporary files
987
- - [ ] Schedule next deployment
988
-
989
- ## Troubleshooting Deployment Issues
990
-
991
- ### 1. Common Deployment Problems
992
-
993
- ```typescript
994
- // utils/deployment-troubleshooting.ts
995
- export const commonDeploymentIssues = {
996
- buildFailures: {
997
- symptoms: ['Build timeout', 'Memory errors', 'Dependency conflicts'],
998
- solutions: [
999
- 'Increase build memory allocation',
1000
- 'Update dependencies',
1001
- 'Clear build cache',
1002
- 'Check for circular dependencies',
1003
- ],
1004
- },
1005
-
1006
- environmentIssues: {
1007
- symptoms: ['Missing environment variables', 'Wrong API endpoints'],
1008
- solutions: [
1009
- 'Verify all required env vars are set',
1010
- 'Check environment-specific configs',
1011
- 'Validate API credentials',
1012
- 'Test API connectivity',
1013
- ],
1014
- },
1015
-
1016
- performanceIssues: {
1017
- symptoms: ['Slow page loads', 'High memory usage'],
1018
- solutions: [
1019
- 'Optimize bundle size',
1020
- 'Implement code splitting',
1021
- 'Add caching strategies',
1022
- 'Monitor resource usage',
1023
- ],
1024
- },
1025
- };
1026
- ```
1027
-
1028
- ### 2. Emergency Rollback
1029
-
1030
- ```bash
1031
- #!/bin/bash
1032
- # emergency-rollback.sh
1033
-
1034
- echo "Starting emergency rollback..."
1035
-
1036
- # Stop current deployment
1037
- echo "Stopping current deployment..."
1038
- # Add your deployment stop commands here
1039
-
1040
- # Rollback to previous version
1041
- echo "Rolling back to previous version..."
1042
- # Add your rollback commands here
1043
-
1044
- # Verify rollback
1045
- echo "Verifying rollback..."
1046
- curl -f https://your-domain.com/health
1047
-
1048
- if [ $? -eq 0 ]; then
1049
- echo "Rollback successful"
1050
- exit 0
1051
- else
1052
- echo "Rollback failed"
1053
- exit 1
1054
- fi
1055
-
1056
- ## ♿ Accessibility
1057
-
1058
- Deployment should maintain accessibility:
1059
-
1060
- - **Production builds maintain accessibility** - Verify accessibility features work in production
1061
- - **Environment variables don't break accessibility** - Ensure accessibility settings are correct
1062
- - **CDN caching doesn't affect accessibility** - Verify cached assets maintain accessibility
1063
- - **Error pages are accessible** - Ensure error pages meet accessibility standards
1064
- - **Monitoring includes accessibility metrics** - Track accessibility in production
1065
-
1066
- ### Accessibility Best Practices
1067
-
1068
- 1. **Test production builds with screen readers** - Verify accessibility works in production
1069
- 2. **Monitor accessibility in production** - Track accessibility metrics
1070
- 3. **Ensure error pages are accessible** - Error pages should meet WCAG standards
1071
- 4. **Test with assistive technologies** - Verify production deployment works with screen readers
1072
- 5. **Document accessibility requirements** - Include accessibility in deployment checklists
1073
-
1074
- ## ⚠️ Edge Cases
1075
-
1076
- ### Deployment Failures
1077
-
1078
- When deployment fails:
1079
- - Have rollback plan ready
1080
- - Test deployment procedures in staging
1081
- - Monitor deployment logs
1082
- - Verify all dependencies are available
1083
- - Test with minimal configuration
1084
-
1085
- ### Environment-Specific Issues
1086
-
1087
- When issues occur in specific environments:
1088
- - Verify environment variables are correct
1089
- - Check build configuration matches environment
1090
- - Ensure all services are available
1091
- - Test with environment-specific data
1092
- - Review environment differences
1093
-
1094
- ### Rollback Scenarios
1095
-
1096
- When rollback is needed:
1097
- - Have automated rollback procedures
1098
- - Test rollback in staging environment
1099
- - Verify data integrity after rollback
1100
- - Document rollback steps clearly
1101
- - Monitor system after rollback
1102
-
1103
- For more information about deploying your application, see the [Security Guide](./security.md) and [Performance Guide](./performance.md).