@etus/bhono-app 0.1.4 → 0.1.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 (270) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.js +0 -0
  3. package/package.json +5 -1
  4. package/templates/base/.husky/pre-push +26 -0
  5. package/templates/base/CLAUDE.md +5 -5
  6. package/templates/base/README.md +31 -20
  7. package/templates/base/docs/app_spec.txt +13 -10
  8. package/templates/base/docs/architecture/README.md +3 -0
  9. package/templates/base/docs/architecture/data-requirements.md +4 -3
  10. package/templates/base/docs/architecture/db-bootstrap.md +39 -0
  11. package/templates/base/docs/architecture/drizzle-migration-plan.md +125 -0
  12. package/templates/base/docs/architecture/erd.md +1 -1
  13. package/templates/base/docs/architecture/sql-standards.md +100 -0
  14. package/templates/base/docs/testing.md +36 -29
  15. package/templates/base/package.json +6 -5
  16. package/templates/base/pnpm-lock.yaml +0 -123
  17. package/templates/base/schema.sql +84 -0
  18. package/templates/base/scripts/init.sh +271 -34
  19. package/templates/base/src/client/hooks/use-auth.ts +5 -0
  20. package/templates/base/src/client/routes/_authenticated/dashboard.tsx +1 -1
  21. package/templates/base/src/client/routes/index.tsx +1 -1
  22. package/templates/base/src/server/db/client.ts +3 -5
  23. package/templates/base/src/server/db/records.ts +81 -0
  24. package/templates/base/src/server/db/seed.ts +3 -2
  25. package/templates/base/src/server/db/sql.ts +96 -0
  26. package/templates/base/src/server/index.ts +16 -2
  27. package/templates/base/src/server/lib/audit.ts +74 -26
  28. package/templates/base/src/server/lib/audited-db.ts +219 -109
  29. package/templates/base/src/server/lib/transaction.ts +10 -16
  30. package/templates/base/src/server/middleware/account.ts +8 -15
  31. package/templates/base/src/server/middleware/auth.ts +102 -38
  32. package/templates/base/src/server/middleware/rate-limit.ts +6 -1
  33. package/templates/base/src/server/routes/accounts/handlers.ts +18 -6
  34. package/templates/base/src/server/routes/audits/handlers.ts +3 -1
  35. package/templates/base/src/server/routes/auth/handlers.ts +14 -9
  36. package/templates/base/src/server/routes/auth/test-login.ts +99 -45
  37. package/templates/base/src/server/routes/health/handlers.ts +4 -4
  38. package/templates/base/src/server/routes/invitations/handlers.ts +6 -3
  39. package/templates/base/src/server/routes/users/handlers.ts +21 -14
  40. package/templates/base/src/server/services/accounts.ts +242 -217
  41. package/templates/base/src/server/services/audits.ts +114 -61
  42. package/templates/base/src/server/services/auth.ts +310 -180
  43. package/templates/base/src/server/services/invitations.ts +282 -222
  44. package/templates/base/src/server/services/users.ts +383 -293
  45. package/templates/base/src/server/types/index.ts +1 -2
  46. package/templates/base/{src/server/__tests__/fixtures.ts → tests/fixtures/server.ts} +3 -3
  47. package/templates/base/{src/client/__tests__/setup-browser.ts → tests/helpers/client-setup-browser.ts} +2 -2
  48. package/templates/base/{src/client/__tests__/setup.ts → tests/helpers/client-setup.ts} +1 -1
  49. package/templates/base/{src/client/__tests__/test-utils.tsx → tests/helpers/client-test-utils.tsx} +2 -2
  50. package/templates/base/{src/server/__tests__/setup.ts → tests/helpers/server.ts} +9 -9
  51. package/templates/base/tests/integration/accounts/crud.test.ts +2 -11
  52. package/templates/base/tests/integration/audits/list.test.ts +2 -11
  53. package/templates/base/tests/integration/auth/auth-service.test.ts +1 -10
  54. package/templates/base/tests/integration/auth/invitation-token.test.ts +2 -11
  55. package/templates/base/tests/integration/auth/logout.test.ts +2 -11
  56. package/templates/base/tests/integration/auth/oauth.test.ts +23 -42
  57. package/templates/base/tests/integration/auth/refresh-token.test.ts +1 -9
  58. package/templates/base/tests/integration/auth/session-expiry.test.ts +1 -9
  59. package/templates/base/tests/integration/auth/session.test.ts +2 -11
  60. package/templates/base/tests/integration/auth/super-admin.test.ts +1 -9
  61. package/templates/base/tests/integration/authorization/analytics-role.test.ts +2 -11
  62. package/templates/base/tests/integration/authorization/billing-role.test.ts +2 -11
  63. package/templates/base/tests/integration/authorization/guards-roles.test.ts +1 -9
  64. package/templates/base/tests/integration/authorization/multi-tenancy.test.ts +2 -11
  65. package/templates/base/tests/integration/authorization/roles.test.ts +2 -11
  66. package/templates/base/tests/integration/config/production-behavior.test.ts +2 -11
  67. package/templates/base/tests/integration/health/health.test.ts +25 -44
  68. package/templates/base/tests/integration/invitations/crud.test.ts +2 -11
  69. package/templates/base/tests/integration/invitations/email.test.ts +1 -9
  70. package/templates/base/tests/integration/middleware/auth.test.ts +3 -12
  71. package/templates/base/tests/integration/middleware/request-logger.test.ts +1 -9
  72. package/templates/base/tests/integration/performance/response-times.test.ts +1 -9
  73. package/templates/base/tests/integration/security/cookie-security.test.ts +2 -11
  74. package/templates/base/tests/integration/security/csrf-protection.test.ts +2 -11
  75. package/templates/base/tests/integration/security/log-sanitization.test.ts +1 -9
  76. package/templates/base/tests/integration/security/rate-limiting.test.ts +1 -9
  77. package/templates/base/tests/integration/security/sql-injection.test.ts +7 -18
  78. package/templates/base/tests/integration/security/xss-prevention.test.ts +2 -11
  79. package/templates/base/tests/integration/setup.ts +13 -90
  80. package/templates/base/tests/integration/smoke.test.ts +3 -2
  81. package/templates/base/tests/integration/storage/upload.test.ts +2 -11
  82. package/templates/base/tests/integration/storage/validation.test.ts +2 -11
  83. package/templates/base/tests/integration/users/crud.test.ts +2 -11
  84. package/templates/base/tests/integration/users/list.test.ts +2 -11
  85. package/templates/base/tests/integration/vitest.config.ts +2 -9
  86. package/templates/base/{src/server/__tests__ → tests}/mocks/db.ts +1 -1
  87. package/templates/base/{src/server/__tests__ → tests}/mocks/index.ts +1 -1
  88. package/templates/base/{src/server/__tests__ → tests}/mocks/kv.ts +1 -1
  89. package/templates/base/{src/server/__tests__ → tests}/mocks/r2.ts +1 -1
  90. package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/sidebar.test.tsx +1 -1
  91. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/avatar.test.tsx +1 -1
  92. package/templates/base/{src/client/__tests__ → tests/unit/client/components/ui}/button.test.tsx +1 -1
  93. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/card.test.tsx +1 -1
  94. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/dialog.test.tsx +1 -1
  95. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/input.test.tsx +1 -1
  96. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/loading-skeleton.test.tsx +1 -1
  97. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/skeleton.test.tsx +1 -1
  98. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/sonner.test.tsx +1 -1
  99. package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/tabs.test.tsx +1 -1
  100. package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/account.test.tsx +1 -1
  101. package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/integrations.test.tsx +1 -1
  102. package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/settings.test.tsx +1 -1
  103. package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/team.test.tsx +1 -1
  104. package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/authenticated-layout.test.tsx +1 -1
  105. package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/dashboard.test.tsx +1 -1
  106. package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/invite.test.tsx +1 -1
  107. package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/login.test.tsx +1 -1
  108. package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/navigation.test.tsx +1 -1
  109. package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/root-layout.test.tsx +1 -1
  110. package/templates/base/{src/server/auth/__tests__ → tests/unit/server/auth}/guards.test.ts +2 -2
  111. package/templates/base/{src → tests/unit}/server/auth/permissions.test.ts +1 -1
  112. package/templates/base/{src → tests/unit}/server/auth/roles.test.ts +1 -1
  113. package/templates/base/tests/unit/server/db/sql.test.ts +68 -0
  114. package/templates/base/{src → tests/unit}/server/env.test.ts +1 -1
  115. package/templates/base/tests/unit/server/lib/audited-db.test.ts +78 -0
  116. package/templates/base/{src → tests/unit}/server/lib/email.test.ts +1 -1
  117. package/templates/base/{src → tests/unit}/server/lib/errors.test.ts +1 -1
  118. package/templates/base/{src → tests/unit}/server/lib/oauth.test.ts +1 -1
  119. package/templates/base/{src → tests/unit}/server/lib/pagination.test.ts +1 -1
  120. package/templates/base/{src → tests/unit}/server/lib/password.test.ts +1 -1
  121. package/templates/base/{src → tests/unit}/server/lib/providers.test.ts +1 -1
  122. package/templates/base/{src → tests/unit}/server/lib/r2-storage.test.ts +2 -2
  123. package/templates/base/{src → tests/unit}/server/lib/session.test.ts +2 -2
  124. package/templates/base/{src → tests/unit}/server/lib/tokens.test.ts +1 -1
  125. package/templates/base/{src → tests/unit}/server/lib/transaction.test.ts +5 -14
  126. package/templates/base/{src → tests/unit}/server/middleware/account.test.ts +16 -24
  127. package/templates/base/{src → tests/unit}/server/middleware/auth.test.ts +71 -42
  128. package/templates/base/{src → tests/unit}/server/middleware/cors.test.ts +1 -1
  129. package/templates/base/{src → tests/unit}/server/middleware/error-handler.test.ts +2 -2
  130. package/templates/base/{src → tests/unit}/server/middleware/rate-limit.test.ts +3 -2
  131. package/templates/base/{src → tests/unit}/server/middleware/request-context.test.ts +1 -1
  132. package/templates/base/{src → tests/unit}/server/middleware/request-logger.test.ts +1 -1
  133. package/templates/base/{src/server/__tests__/mocks/__tests__ → tests/unit/server/mocks}/db.test.ts +1 -1
  134. package/templates/base/{src/server/__tests__/mocks/__tests__ → tests/unit/server/mocks}/kv.test.ts +1 -1
  135. package/templates/base/{src/server/__tests__/mocks/__tests__ → tests/unit/server/mocks}/r2.test.ts +1 -1
  136. package/templates/base/{src/server/routes/accounts/__tests__ → tests/unit/server/routes/accounts}/handlers.test.ts +12 -12
  137. package/templates/base/{src/server/routes/audits/__tests__ → tests/unit/server/routes/audits}/handlers.test.ts +11 -11
  138. package/templates/base/{src/server/routes/auth/__tests__ → tests/unit/server/routes/auth}/handlers.test.ts +13 -13
  139. package/templates/base/{src/server/routes/health/__tests__ → tests/unit/server/routes/health}/handlers.test.ts +27 -23
  140. package/templates/base/{src/server/routes/invitations/__tests__ → tests/unit/server/routes/invitations}/handlers.test.ts +14 -17
  141. package/templates/base/{src/server/routes/storage/__tests__ → tests/unit/server/routes/storage}/handlers.test.ts +6 -6
  142. package/templates/base/{src/server/routes/users/__tests__ → tests/unit/server/routes/users}/handlers.test.ts +12 -12
  143. package/templates/base/tests/unit/server/services/accounts.test.ts +258 -0
  144. package/templates/base/tests/unit/server/services/audits.test.ts +141 -0
  145. package/templates/base/tests/unit/server/services/auth.test.ts +179 -0
  146. package/templates/base/tests/unit/server/services/invitations.test.ts +165 -0
  147. package/templates/base/tests/unit/server/services/users.test.ts +351 -0
  148. package/templates/base/tsconfig.json +2 -1
  149. package/templates/base/vitest.config.browser.ts +3 -2
  150. package/templates/base/vitest.config.frontend.ts +3 -2
  151. package/templates/base/vitest.config.ts +7 -14
  152. package/templates/base/.claude/settings.local.json +0 -11
  153. package/templates/base/config/drizzle.config.ts +0 -10
  154. package/templates/base/src/server/db/schema/accounts.ts +0 -20
  155. package/templates/base/src/server/db/schema/audit-logs.ts +0 -26
  156. package/templates/base/src/server/db/schema/index.ts +0 -7
  157. package/templates/base/src/server/db/schema/invitations.ts +0 -30
  158. package/templates/base/src/server/db/schema/refresh-tokens.ts +0 -22
  159. package/templates/base/src/server/db/schema/user-accounts.ts +0 -25
  160. package/templates/base/src/server/db/schema/users.ts +0 -33
  161. package/templates/base/src/server/lib/audited-db.test.ts +0 -107
  162. package/templates/base/src/server/lib/schema-helpers.ts +0 -16
  163. package/templates/base/src/server/services/__tests__/accounts.test.ts +0 -764
  164. package/templates/base/src/server/services/__tests__/audits.test.ts +0 -235
  165. package/templates/base/src/server/services/__tests__/auth.test.ts +0 -765
  166. package/templates/base/src/server/services/__tests__/invitations.test.ts +0 -704
  167. package/templates/base/src/server/services/__tests__/users.test.ts +0 -755
  168. package/templates/base/tests/integration/lib/schema-helpers.test.ts +0 -129
  169. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-can-be-collapsed-by-default-1.png +0 -0
  170. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-expands-when-collapsed-and-expand-button-is-clicked-1.png +0 -0
  171. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-handles-logout-button-click-1.png +0 -0
  172. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-handles-navigation-clicks-1.png +0 -0
  173. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-hides-navigation-labels-when-collapsed-1.png +0 -0
  174. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-highlights-active-route-1.png +0 -0
  175. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-renders-sidebar-navigation-items-1.png +0 -0
  176. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-shows-keyboard-shortcut-hint-when-expanded-1.png +0 -0
  177. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-info-when-authenticated-1.png +0 -0
  178. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-initials-in-avatar-fallback-1.png +0 -0
  179. /package/templates/base/{src/client/components/__tests__ → tests/unit/client/components}/error-boundary.test.tsx +0 -0
  180. /package/templates/base/{src/client/components/ui/__tests__ → tests/unit/client/components/ui}/error-fallback.test.tsx +0 -0
  181. /package/templates/base/{src/client/hooks/__tests__ → tests/unit/client/hooks}/use-auth.test.tsx +0 -0
  182. /package/templates/base/{src/client/hooks/__tests__ → tests/unit/client/hooks}/use-theme.test.tsx +0 -0
  183. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-dashboard-stats-cards-1.png +0 -0
  184. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-quick-action-cards-1.png +0 -0
  185. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-recent-activity-section-1.png +0 -0
  186. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-first-name-in-welcome-message-1.png +0 -0
  187. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-information-in-sidebar-1.png +0 -0
  188. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-render-dashboard-when-authenticated-1.png +0 -0
  189. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-show-navigation-sidebar-1.png +0 -0
  190. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-unauthenticated-should-redirect-to-login-when-not-authenticated-1.png +0 -0
  191. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-accept-invitation-button-1.png +0 -0
  192. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-decline-button-linking-to-homepage-1.png +0 -0
  193. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-invitation-details--email--workspace--role--1.png +0 -0
  194. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-have-a-logo-link-to-homepage-1.png +0 -0
  195. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-render-invitation-page-with-inviter-name-and-workspace-1.png +0 -0
  196. /package/templates/base/{src/client/routes/__tests__ → tests/unit/client/routes}/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-show-terms-of-service-and-privacy-policy-links-1.png +0 -0
  197. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-display-Google-OAuth-login-button-1.png +0 -0
  198. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-have-a-link-back-to-home-page-1.png +0 -0
  199. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-content-without-waiting-for-authentication-1.png +0 -0
  200. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-page-at--login-route-1.png +0 -0
  201. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-show-Terms-of-Service-and-Privacy-Policy-links-1.png +0 -0
  202. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/login.test.tsx/Login-Page-should-trigger-OAuth-flow-when-clicking-login-button-1.png +0 -0
  203. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-display-404-text-on-not-found-page-1.png +0 -0
  204. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-have-navigation-options-on-404-page-1.png +0 -0
  205. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-render-404-page-for-unknown-routes-1.png +0 -0
  206. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-account-page-1.png +0 -0
  207. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-integrations-page-1.png +0 -0
  208. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-settings-page-1.png +0 -0
  209. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-team-page-1.png +0 -0
  210. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-display-navigation-links-on-home-page-1.png +0 -0
  211. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-have-correct-link-destinations-on-home-page-1.png +0 -0
  212. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-home-page-without-authentication-1.png +0 -0
  213. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-login-page-without-authentication-1.png +0 -0
  214. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-dashboard-to-login-1.png +0 -0
  215. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-settings-to-login-1.png +0 -0
  216. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-team-to-login-1.png +0 -0
  217. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-render-Active-Sessions-section-with-session-cards-1.png +0 -0
  218. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-render-page-with-correct-title--Account--1.png +0 -0
  219. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-show-API-Access-section-1.png +0 -0
  220. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-show-Connected-Accounts-section-with-Google-connected-1.png +0 -0
  221. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-show-Danger-Zone-section-with-delete-button-1.png +0 -0
  222. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/account.test.tsx/Account-Page-should-show-Security-section-with-Two-Factor-Authentication-1.png +0 -0
  223. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-API-documentation-section-should-display-API-documentation-link-section-1.png +0 -0
  224. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-Create-Webhook-Dialog-should-have-Add-Webhook-trigger-button-1.png +0 -0
  225. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-category-filters-should-display-all-category-buttons-1.png +0 -0
  226. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-all-integration-cards-with-names-1.png +0 -0
  227. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-category-badges-on-cards-1.png +0 -0
  228. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Configure-button-for-connected-integrations-1.png +0 -0
  229. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connect-button-for-not-connected-integrations-1.png +0 -0
  230. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connected-badge-for-connected-integrations-1.png +0 -0
  231. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Available-Integrations-section-1.png +0 -0
  232. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Webhooks-section-1.png +0 -0
  233. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-connected-count-1.png +0 -0
  234. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-page-description-1.png +0 -0
  235. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-search-input-1.png +0 -0
  236. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-render-with-correct-title--Integrations--1.png +0 -0
  237. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-filter-integrations-based-on-search-query-1.png +0 -0
  238. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-search-by-description-1.png +0 -0
  239. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-show-no-results-message-when-search-has-no-matches-1.png +0 -0
  240. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-existing-webhook-1.png +0 -0
  241. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-events-1.png +0 -0
  242. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-last-delivery-info-1.png +0 -0
  243. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-success-status-1.png +0 -0
  244. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-have-Add-Webhook-button-1.png +0 -0
  245. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-connected-accounts-section-with-Google-provider-1.png +0 -0
  246. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-sessions-and-danger-zone-sections-1.png +0 -0
  247. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-all-notification-toggle-options-1.png +0 -0
  248. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-email-notifications-section-1.png +0 -0
  249. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-toggle-switches-for-notification-options-1.png +0 -0
  250. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-have-toggles-checked-by-default-1.png +0 -0
  251. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display--Save-Changes--button-1.png +0 -0
  252. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-personal-information-form-1.png +0 -0
  253. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-profile-picture-section-1.png +0 -0
  254. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-email-in-disabled-email-input-1.png +0 -0
  255. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-initials-in-avatar-1.png +0 -0
  256. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-name-in-the-name-input-1.png +0 -0
  257. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-all-three-tabs-1.png +0 -0
  258. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-page-description-1.png +0 -0
  259. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-render-with-correct-title--Settings--1.png +0 -0
  260. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-show-Profile-tab-as-default-active-tab-1.png +0 -0
  261. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Account-tab-when-clicked-1.png +0 -0
  262. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Notifications-tab-when-clicked-1.png +0 -0
  263. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-display-Active-Members-section-with-member-count-1.png +0 -0
  264. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-display-Pending-Invitations-section-with-invitation-details-1.png +0 -0
  265. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-have-invite-member-button-that-can-be-clicked-1.png +0 -0
  266. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-render-page-with-correct-title-and-description-1.png +0 -0
  267. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-render-search-input-that-filters-team-members-1.png +0 -0
  268. /package/templates/base/{src/client/routes/_authenticated/__tests__ → tests/unit/client/routes/_authenticated}/__screenshots__/team.test.tsx/Team-Page-should-show-current-user-with---you---indicator-and-role-badge-1.png +0 -0
  269. /package/templates/base/{src/client/__tests__ → tests/unit/client}/routes/error-components.test.tsx +0 -0
  270. /package/templates/base/{src/shared/schemas/__tests__ → tests/unit/shared}/schemas.test.ts +0 -0
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ function buildProgram() {
13
13
  return new Command()
14
14
  .name('bhono-app')
15
15
  .description('Create a new project from the Etus boilerplate')
16
- .version('0.1.4')
16
+ .version('0.1.5')
17
17
  .argument('<project-name>', 'Name of the project')
18
18
  .option('-d, --domain <domain>', 'Production domain')
19
19
  .option('-m, --modules <modules>', 'Comma-separated modules to include')
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "@etus/bhono-app",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/etusdigital/bhono"
8
+ },
5
9
  "files": [
6
10
  "dist",
7
11
  "templates"
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env sh
2
+
3
+ echo "🔍 Running pre-push checks..."
4
+
5
+ # Type checking
6
+ echo "📝 Type checking..."
7
+ pnpm typecheck || {
8
+ echo "❌ Type check failed. Push aborted."
9
+ exit 1
10
+ }
11
+
12
+ # Server unit tests only (faster, more reliable)
13
+ echo "🧪 Running server unit tests..."
14
+ pnpm test:unit:server || {
15
+ echo "❌ Server unit tests failed. Push aborted."
16
+ exit 1
17
+ }
18
+
19
+ # Build verification
20
+ echo "🏗️ Verifying build..."
21
+ pnpm build || {
22
+ echo "❌ Build failed. Push aborted."
23
+ exit 1
24
+ }
25
+
26
+ echo "✅ All pre-push checks passed!"
@@ -5,7 +5,7 @@ Production-ready multi-tenant SaaS boilerplate with Hono.js backend and React fr
5
5
  ## Tech Stack
6
6
 
7
7
  - **Runtime**: Cloudflare Workers (D1 database, KV sessions, R2 storage)
8
- - **Backend**: Hono.js 4.6 + Drizzle ORM + Zod validation
8
+ - **Backend**: Hono.js 4.6 + SQL (D1) + Zod validation
9
9
  - **Frontend**: React 19 + TanStack Router + Tailwind CSS 4.0
10
10
  - **Testing**: Vitest (unit/integration) + Playwright (E2E)
11
11
  - **Auth**: Google OAuth 2.0 with session-based cookies
@@ -33,7 +33,7 @@ Production-ready multi-tenant SaaS boilerplate with Hono.js backend and React fr
33
33
  │ │ │ └── health/ # Health check
34
34
  │ │ ├── services/ # Business logic layer
35
35
  │ │ ├── middleware/ # Auth, CORS, logging, rate-limit
36
- │ │ ├── db/schema/ # Drizzle table definitions
36
+ │ │ ├── db/records.ts # DB record types for SQL mapping
37
37
  │ │ ├── lib/ # Utilities (oauth, session, tokens)
38
38
  │ │ └── auth/ # Roles, permissions, guards
39
39
  │ │
@@ -213,6 +213,6 @@ Defined in `config/wrangler.json`:
213
213
 
214
214
  ### Database Changes
215
215
 
216
- 1. Modify schema in `src/server/db/schema/`
217
- 2. Run `pnpm drizzle-kit generate` to create migration
218
- 3. Apply with `pnpm db:migrate:local`
216
+ 1. Update `schema.sql`
217
+ 2. Apply with `pnpm db:schema:local`
218
+ 3. (Optional) Seed with `pnpm db:seed:local`
@@ -52,7 +52,7 @@ This boilerplate provides everything you need to build a modern, secure, and sca
52
52
  - Rate limiting middleware (in-memory with lazy cleanup)
53
53
  - CSRF protection via SameSite cookies
54
54
  - XSS prevention with secure headers
55
- - SQL injection protection via Drizzle ORM
55
+ - SQL injection protection via parameterized queries
56
56
 
57
57
  ### Testing
58
58
  - Unit tests with Vitest (94%+ coverage)
@@ -73,7 +73,7 @@ This boilerplate provides everything you need to build a modern, secure, and sca
73
73
  | **Backend** | Hono.js 4.6 |
74
74
  | **Frontend** | React 19 + TanStack Router |
75
75
  | **Database** | Cloudflare D1 (SQLite) |
76
- | **ORM** | Drizzle ORM |
76
+ | **Data Access** | SQL helpers (D1) |
77
77
  | **Sessions** | Cloudflare KV |
78
78
  | **Storage** | Cloudflare R2 |
79
79
  | **Styling** | Tailwind CSS 4.0 |
@@ -105,11 +105,11 @@ pnpm install
105
105
  # Copy environment variables
106
106
  cp .env.example .env
107
107
 
108
- # Apply database migrations
109
- pnpm db:migrate:local
108
+ # Apply database schema
109
+ pnpm db:schema:local
110
110
 
111
111
  # Seed test data (optional)
112
- pnpm db:seed
112
+ pnpm db:seed:local
113
113
 
114
114
  # Start development server
115
115
  pnpm dev
@@ -152,7 +152,6 @@ LOG_LEVEL=info
152
152
  ├── config/ # Configuration files
153
153
  │ ├── eslint.config.js # ESLint configuration
154
154
  │ ├── wrangler.json # Cloudflare Workers config
155
- │ ├── drizzle.config.ts # Drizzle ORM config
156
155
  │ └── ...
157
156
 
158
157
  ├── src/
@@ -166,8 +165,11 @@ LOG_LEVEL=info
166
165
  │ │ │ └── storage/ # File storage (R2)
167
166
  │ │ ├── services/ # Business logic
168
167
  │ │ ├── middleware/ # Request middleware
169
- │ │ ├── db/ # Database (Drizzle ORM)
170
- │ │ │ └── schema/ # Table definitions
168
+ │ │ ├── db/ # Database (SQL helpers)
169
+ │ │ │ ├── client.ts # D1 client wrapper
170
+ │ │ │ ├── records.ts # Record typings (SQL results)
171
+ │ │ │ ├── sql.ts # Query helpers (queryOne/queryAll/execute)
172
+ │ │ │ └── seed.ts # Seed generator (seed.sql)
171
173
  │ │ ├── auth/ # Roles, permissions, guards
172
174
  │ │ └── lib/ # Utilities
173
175
  │ │
@@ -209,7 +211,8 @@ LOG_LEVEL=info
209
211
  ├── docs/ # Documentation
210
212
  │ └── testing.md # Testing guide
211
213
 
212
- └── migrations/ # D1 SQL migrations
214
+ ├── schema.sql # D1 schema (source of truth)
215
+ └── seed.sql # Generated seed data
213
216
  ```
214
217
 
215
218
  ---
@@ -300,14 +303,20 @@ invitations (
300
303
  )
301
304
  ```
302
305
 
303
- ### Migrations
306
+ ### Database Schema
304
307
 
305
308
  ```bash
306
- # Apply migrations locally
307
- pnpm db:migrate:local
309
+ # Apply schema.sql locally
310
+ pnpm db:schema:local
308
311
 
309
- # Apply migrations to production
310
- pnpm db:migrate:remote
312
+ # Apply schema.sql to production (optional)
313
+ pnpm db:schema:remote
314
+
315
+ # Generate + seed locally
316
+ pnpm db:seed:local
317
+
318
+ # Full reset (schema + seed)
319
+ pnpm db:reset:local
311
320
 
312
321
  # Generate Cloudflare types
313
322
  pnpm cf-typegen
@@ -556,7 +565,7 @@ Client (React SPA)
556
565
  │ │ │
557
566
  │ ▼ │
558
567
  │ ┌─────────────────────────────┐ │
559
- │ │ Drizzle ORM │ │
568
+ │ │ SQL Helpers │ │
560
569
  │ └─────────────────────────────┘ │
561
570
  │ │ │
562
571
  └──────────────┼────────────────────┘
@@ -586,9 +595,11 @@ import { createUser } from '@server/services/users' // Server
586
595
  | `pnpm lint` | Run ESLint |
587
596
  | `pnpm typecheck` | Run TypeScript checks |
588
597
  | **Database** | |
589
- | `pnpm db:migrate:local` | Apply local migrations |
590
- | `pnpm db:migrate:remote` | Apply remote migrations |
591
- | `pnpm db:seed` | Seed database |
598
+ | `pnpm db:schema:local` | Apply schema.sql locally |
599
+ | `pnpm db:schema:remote` | Apply schema.sql remotely |
600
+ | `pnpm db:seed` | Generate seed.sql |
601
+ | `pnpm db:seed:local` | Generate + seed locally |
602
+ | `pnpm db:reset:local` | Apply schema + seed locally |
592
603
  | `pnpm cf-typegen` | Generate Cloudflare types |
593
604
  | **API** | |
594
605
  | `pnpm api:spec` | Generate OpenAPI spec (docs/openapi.json) |
@@ -614,7 +625,7 @@ import { createUser } from '@server/services/users' // Server
614
625
  - **CSRF**: SameSite cookies + CORS validation
615
626
  - **XSS**: Secure headers + React's built-in escaping
616
627
  - **Session Hijacking**: httpOnly cookies, secure flag in production
617
- - **SQL Injection**: Parameterized queries via Drizzle ORM
628
+ - **SQL Injection**: Parameterized queries via SQL helpers
618
629
  - **Rate Limiting**: In-memory store with configurable limits per route
619
630
  - **Fingerprint Validation**: User-agent validation for sessions
620
631
 
@@ -663,7 +674,7 @@ MIT License - see [LICENSE](LICENSE) for details.
663
674
  ## Acknowledgments
664
675
 
665
676
  - [Hono.js](https://hono.dev/) - Ultrafast web framework
666
- - [Drizzle ORM](https://orm.drizzle.team/) - TypeScript ORM
677
+ - [Cloudflare D1](https://developers.cloudflare.com/d1/) - Serverless SQLite
667
678
  - [TanStack Router](https://tanstack.com/router) - Type-safe routing
668
679
  - [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS
669
680
  - [Cloudflare Workers](https://workers.cloudflare.com/) - Edge computing platform
@@ -42,12 +42,12 @@
42
42
 
43
43
  <backend>
44
44
  <framework>Hono.js 4.6</framework>
45
- <orm>Drizzle ORM</orm>
45
+ <orm>SQL (D1/SQLite)</orm>
46
46
  <validation>Zod</validation>
47
47
  <documentation>OpenAPI 3.0 / Swagger UI</documentation>
48
48
  <description>
49
49
  Type-safe API development with automatic schema generation.
50
- Drizzle provides compile-time SQL safety with SQLite dialect.
50
+ SQL-first access with Cloudflare D1 (SQLite under the hood).
51
51
  OpenAPI spec and TypeScript types can be generated locally (api:spec, api:types).
52
52
  </description>
53
53
  </backend>
@@ -120,7 +120,7 @@
120
120
  → Fetch API
121
121
  → Hono Routes
122
122
  → Services
123
- Drizzle ORM
123
+ SQL (D1/SQLite)
124
124
  → D1 Database
125
125
  </data_flow>
126
126
  </architecture>
@@ -769,9 +769,11 @@
769
769
  npm run build # Build for production
770
770
  npm run deploy # Deploy to Cloudflare Workers
771
771
 
772
- npm run db:migrate:local # Apply migrations locally
773
- npm run db:migrate:remote # Apply migrations to production
774
- npm run db:seed # Seed test data
772
+ npm run db:schema:local # Apply schema.sql locally
773
+ npm run db:schema:remote # Apply schema.sql to production (optional)
774
+ npm run db:seed # Generate seed.sql
775
+ npm run db:seed:local # Generate + seed locally
776
+ npm run db:reset:local # Apply schema.sql + seed (local)
775
777
 
776
778
  npm run test:unit:server # Backend unit tests
777
779
  npm run test:unit:client # Frontend tests
@@ -813,8 +815,8 @@
813
815
  │ ├── services/ # Business logic
814
816
  │ ├── middleware/ # Auth, CORS, logging
815
817
  │ ├── db/
816
- │ │ ├── schema/ # Drizzle table definitions
817
- │ │ └── migrations/ # SQL migrations
818
+ │ │ ├── records.ts # DB record types for SQL mapping
819
+ │ │ └── seed.ts # Seed generator (outputs seed.sql)
818
820
  │ ├── lib/ # Utilities
819
821
  │ └── auth/ # RBAC guards
820
822
 
@@ -836,11 +838,12 @@
836
838
  <key_files>
837
839
  src/server/index.ts # Hono app entry
838
840
  src/server/routes/index.ts # API router
839
- src/server/db/schema/ # Database schema
841
+ src/server/db/records.ts # Database record types
840
842
  src/client/routes/__root.tsx # React app root
841
843
  src/client/routes/_authenticated.tsx # Auth layout
842
844
  wrangler.json # Cloudflare config
843
- drizzle.config.ts # Drizzle ORM config
845
+ schema.sql # SQL schema (source of truth)
846
+ seed.sql # Generated seed data (output)
844
847
  playwright.config.ts # E2E test config
845
848
  vitest.config.ts # Unit test config
846
849
  </key_files>
@@ -6,3 +6,6 @@ Indice rapido dos documentos de arquitetura.
6
6
 
7
7
  - `docs/architecture/erd.md` - ERD e dicionario de dados.
8
8
  - `docs/architecture/data-requirements.md` - Data Requirements Document (DRD).
9
+ - `docs/architecture/db-bootstrap.md` - Bootstrap do schema.sql e seed.
10
+ - `docs/architecture/drizzle-migration-plan.md` - Mapeamento do Drizzle e plano de migracao para SQL puro.
11
+ - `docs/architecture/sql-standards.md` - Padrao de SQL puro e mapeamento de resultados.
@@ -1,7 +1,7 @@
1
1
  # Data Requirements Document (DRD)
2
2
 
3
3
  ## 1. Objetivo e escopo
4
- Este documento define os requisitos de dados do projeto, cobrindo o modelo relacional (D1/SQLite), armazenamento de sessao (KV) e objetos (R2). Serve como referencia para manutencao, auditoria e eventual migracao para SQL puro.
4
+ Este documento define os requisitos de dados do projeto, cobrindo o modelo relacional (D1/SQLite), armazenamento de sessao (KV) e objetos (R2). Serve como referencia para manutencao, auditoria e evolucao do SQL puro.
5
5
 
6
6
  ## 2. Componentes de armazenamento
7
7
  - D1 (SQLite): armazenamento relacional principal.
@@ -102,8 +102,9 @@ Principais entidades:
102
102
  - Requisito: manter procedimento de backup/restore do D1 (ex.: exportacao periodica) e verificar restauracao.
103
103
  - KV e R2 devem ter estrategia de recuperacao alinhada com RPO/RTO desejados.
104
104
 
105
- ## 12. Consideracoes para migracao para SQL puro
105
+ ## 12. Consideracoes para SQL puro (sem migrations)
106
106
  - Todas as queries devem ser parametrizadas para evitar SQL injection.
107
107
  - Manter mapeadores de resultado (ex.: validacao via Zod) para preservar contratos tipados.
108
108
  - Centralizar SQL em um modulo `db` e reutilizar modelos do ERD.
109
- - Implementar migracoes em SQL (ou manter ferramenta atual apenas para migrar schema).
109
+ - `schema.sql` e a fonte de verdade do schema e deve ser aplicado via `wrangler d1 execute`.
110
+ - `seed.sql` e gerado a partir de `src/server/db/seed.ts` e aplicado apos o bootstrap quando necessario.
@@ -0,0 +1,39 @@
1
+ # Database Bootstrap (schema.sql)
2
+
3
+ ## Objetivo
4
+ O boilerplate nao usa migrations. O schema do D1 e versionado em `schema.sql` e aplicado via `wrangler d1 execute`. O seed e gerado em `seed.sql` a partir de `src/server/db/seed.ts`.
5
+
6
+ ## Arquivos
7
+ - `schema.sql` - fonte de verdade do schema
8
+ - `src/server/db/seed.ts` - gerador de seed
9
+ - `seed.sql` - output do seed (gerado)
10
+
11
+ ## Fluxos recomendados
12
+ ### Local
13
+ ```bash
14
+ # aplicar schema
15
+ pnpm db:schema:local
16
+
17
+ # gerar e aplicar seed
18
+ pnpm db:seed:local
19
+
20
+ # reset completo (schema + seed)
21
+ pnpm db:reset:local
22
+ ```
23
+
24
+ ### Remoto (opcional)
25
+ ```bash
26
+ # aplicar schema
27
+ pnpm db:schema:remote
28
+
29
+ # gerar e aplicar seed
30
+ pnpm db:seed:remote
31
+
32
+ # reset completo (schema + seed)
33
+ pnpm db:reset:remote
34
+ ```
35
+
36
+ ## Notas
37
+ - `schema.sql` deve ser atualizado a cada mudanca estrutural.
38
+ - `seed.sql` deve ser re-gerado apos alteracoes em `seed.ts`.
39
+ - As migrations nao sao usadas neste boilerplate para manter o fluxo simples.
@@ -0,0 +1,125 @@
1
+ # Mapeamento do Drizzle e plano de migracao para SQL puro
2
+
3
+ > Status: Drizzle removido (PDB-823, Jan 2026). Este documento permanece como historico do plano.
4
+
5
+ Contexto canonico: `docs/app_spec.txt`.
6
+
7
+ ## Objetivo
8
+
9
+ Documentar onde o Drizzle e utilizado hoje e propor uma sequencia de migracao para SQL puro (D1/SQLite) com menor risco.
10
+
11
+ ## Inventario de uso do Drizzle
12
+
13
+ ### Tooling e configuracao
14
+
15
+ - `config/drizzle.config.ts`
16
+ - `package.json` (scripts `db:push`, `db:generate`, `db:studio`; dependencias `drizzle-orm`, `drizzle-kit`)
17
+ - `packages/bhono-app/templates/base/config/drizzle.config.ts`
18
+ - `packages/bhono-app/templates/base/package.json` (mesmos scripts/dependencias)
19
+
20
+ ### Schema e helpers
21
+
22
+ - `src/server/db/schema/index.ts`
23
+ - `src/server/db/schema/*.ts` (users, accounts, user-accounts, invitations, refresh-tokens, audit-logs)
24
+ - `src/server/lib/schema-helpers.ts`
25
+ - `packages/bhono-app/templates/base/src/server/db/schema/*`
26
+ - `packages/bhono-app/templates/base/src/server/lib/schema-helpers.ts`
27
+
28
+ ### Client e cross-cutting
29
+
30
+ - `src/server/db/client.ts` (createDb com `drizzle-orm/d1`)
31
+ - `src/server/lib/transaction.ts` (types baseados em `Database['transaction']`)
32
+ - `src/server/lib/audited-db.ts` (Table/SQL do Drizzle, `.returning()`)
33
+ - `src/server/lib/audit.ts` (grava em `audit_logs` usando `db.insert`)
34
+ - `packages/bhono-app/templates/base/src/server/db/client.ts`
35
+ - `packages/bhono-app/templates/base/src/server/lib/transaction.ts`
36
+ - `packages/bhono-app/templates/base/src/server/lib/audited-db.ts`
37
+ - `packages/bhono-app/templates/base/src/server/lib/audit.ts`
38
+
39
+ ### Services (queries principais)
40
+
41
+ - `src/server/services/auth.ts` (insert/update/returning, tokens, refresh)
42
+ - `src/server/services/users.ts` (filtros, subquery IN, soft delete, paginacao)
43
+ - `src/server/services/accounts.ts` (filtros, subquery IN, soft delete, paginacao)
44
+ - `src/server/services/invitations.ts` (joins, expiracao, create/accept)
45
+ - `src/server/services/audits.ts` (filtros, paginacao)
46
+ - `packages/bhono-app/templates/base/src/server/services/*` (espelho)
47
+
48
+ ### Middleware e rotas
49
+
50
+ - `src/server/middleware/auth.ts` (select por id + soft delete)
51
+ - `src/server/middleware/account.ts` (select por membership)
52
+ - `src/server/routes/health/handlers.ts` (db.run com `sql` do Drizzle)
53
+ - `src/server/routes/auth/test-login.ts` (select simples)
54
+ - `packages/bhono-app/templates/base/src/server/middleware/*`
55
+ - `packages/bhono-app/templates/base/src/server/routes/*`
56
+
57
+ ### Testes
58
+
59
+ - `tests/integration/setup.ts` (drizzle + better-sqlite3, schema SQL inline)
60
+ - `packages/bhono-app/templates/base/tests/integration/*` (espelho com drizzle)
61
+ - `packages/bhono-app/templates/base/tests/integration/security/*.test.ts` (comentarios e wrappers de drizzle)
62
+
63
+ ## Padroes de query usados hoje
64
+
65
+ - Select simples por id + soft delete (`deleted_at IS NULL`).
66
+ - Select com join (`invitations` + `users`/`accounts`).
67
+ - Subquery com `IN` (multi-tenancy em users/accounts).
68
+ - Paginacao com `LIMIT/OFFSET` + `count(*)`.
69
+ - `LIKE` para filtros por nome/email/dominio.
70
+ - Inserts/updates com `returning()`.
71
+ - Soft delete (update de `deleted_at` e audit).
72
+ - Transacoes (create user + account + membership; depende de `db.transaction`).
73
+ - Uso pontual de SQL raw (`sql\`SELECT 1\`` na healthcheck).
74
+
75
+ ## Sequencia recomendada de migracao
76
+
77
+ 1) Padroes e convencoes de SQL puro (PDB-813)
78
+ - Definir placeholders, naming, soft delete, mapeamento/validacao, tratamento de erros.
79
+
80
+ 2) Helper SQL para D1 (PDB-814)
81
+ - API de execucao (queryOne/queryAll/exec), bind de parametros e typing.
82
+ - Confirmar comportamento de transacoes no D1 (ex.: `batch`) antes de migrar flows criticos.
83
+
84
+ 3) Camadas cross-cutting (PDB-815)
85
+ - Reimplementar `audited-db` e `audit` com SQL puro.
86
+ - Ajustar `transaction.ts` para o novo helper.
87
+
88
+ 4) Modulos de negocio (PDB-816 a PDB-821)
89
+ - Auth -> Users -> Accounts -> Invitations -> Audits -> Middleware.
90
+ - Sempre migrar junto com testes afetados.
91
+
92
+ 5) Estrategia sem migrations (PDB-822)
93
+ - Consolidar `schema.sql` versionado e bootstrap/reset com `wrangler d1 execute`.
94
+ - Alinhar `tests/integration/setup.ts` com `schema.sql`.
95
+
96
+ 6) Remocao de Drizzle (PDB-823)
97
+ - Limpar dependencias, scripts e tipos remanescentes.
98
+
99
+ ## Riscos e mitigacoes
100
+
101
+ - Consistencia multi-tenant: garantir `account_id` em todas as queries.
102
+ - Mitigacao: helper com scoping obrigatorio e testes de autorizacao.
103
+
104
+ - Perda de audit trail: `audited-*` depende de `returning()`.
105
+ - Mitigacao: selecionar estado anterior antes do update e usar `RETURNING` quando suportado.
106
+
107
+ - SQL injection: migracao aumenta risco manual.
108
+ - Mitigacao: prepared statements, helpers obrigatorios e proibicao de string interpolation.
109
+
110
+ - Diferencas de comportamento entre D1 e sqlite local.
111
+ - Mitigacao: alinhar `schema.sql` e tests com D1 (usar `wrangler d1` para smoke tests).
112
+
113
+ - Quebra de testes e mocks.
114
+ - Mitigacao: atualizar `tests/integration/setup.ts` e mocks ao mesmo tempo que cada modulo.
115
+
116
+ ## Entregaveis desta etapa (PDB-812)
117
+
118
+ - Inventario de arquivos e padroes de query.
119
+ - Sequencia recomendada e dependencias entre modulos.
120
+ - Riscos e mitigacoes para orientar as proximas issues.
121
+
122
+ ## Notas
123
+
124
+ - Tudo que for alterado no `src/` deve ser espelhado em `packages/bhono-app/templates/base/`.
125
+ - O seed ja gera SQL puro; pode ser mantido e ajustado conforme o `schema.sql`.
@@ -1,7 +1,7 @@
1
1
  # ERD - Hono Boilerplate (D1/SQLite)
2
2
 
3
3
  ## Visao geral
4
- Este documento descreve o modelo relacional atual utilizado no banco D1 (SQLite) do projeto. Ele foi derivado diretamente dos schemas em `src/server/db/schema`.
4
+ Este documento descreve o modelo relacional atual utilizado no banco D1 (SQLite) do projeto. Ele foi derivado diretamente de `schema.sql`.
5
5
 
6
6
  ## Diagrama (Mermaid)
7
7
  ```mermaid
@@ -0,0 +1,100 @@
1
+ # Padrao de SQL puro e mapeamento de resultados
2
+
3
+ Contexto canonico: `docs/app_spec.txt`.
4
+
5
+ ## Objetivo
6
+
7
+ Definir convencoes para SQL puro no D1/SQLite, incluindo bind de parametros,
8
+ mapa de resultados e tratamento de erros para manter consistencia e seguranca.
9
+
10
+ ## Escopo
11
+
12
+ - SQL usado no backend (services, middleware, lib).
13
+ - Mapeamento de resultados para tipos de dominio.
14
+ - Soft delete, multi-tenancy, auditoria e paginacao.
15
+
16
+ ## Convencoes de SQL
17
+
18
+ ### Estilo
19
+
20
+ - Keywords em UPPERCASE (SELECT, FROM, WHERE).
21
+ - Tabelas e colunas em snake_case (como no schema atual).
22
+ - Evitar `SELECT *`: listar colunas para mapear explicitamente.
23
+ - Preferir alias curtos (`users u`, `accounts a`) quando houver join.
24
+
25
+ ### Parametros e seguranca
26
+
27
+ - Nunca interpolar strings diretamente em SQL.
28
+ - Usar placeholders posicionais `?` com `stmt.bind(...)`.
29
+ - Proibir concatenacao de SQL com valores de usuario.
30
+
31
+ ### Soft delete
32
+
33
+ - Queries de leitura devem sempre filtrar `deleted_at IS NULL` quando aplicavel.
34
+ - Remocoes devem ser soft delete (update de `deleted_at`, `deleted_by_id`, `updated_at`).
35
+ - Restauracao deve limpar `deleted_at` e `deleted_by_id`.
36
+
37
+ ### Multi-tenancy
38
+
39
+ - Toda query de dados multi-tenant deve filtrar `account_id`.
40
+ - Para super-admin, permitir bypass explicito em query (flag de contexto).
41
+
42
+ ### Paginacao e filtros
43
+
44
+ - Paginacao via `LIMIT`/`OFFSET`.
45
+ - Contagem total via `SELECT count(*)`.
46
+ - Filtros textuais com `LIKE` e `%`.
47
+
48
+ ### Datas e tipos
49
+
50
+ - Datas em TEXT ISO (ex.: `created_at`) ou INTEGER unix (ex.: `refresh_tokens`).
51
+ - Mapear `INTEGER` para boolean quando necessario (0/1).
52
+ - Campos JSON em TEXT devem ser parseados ao ler.
53
+
54
+ ## Mapeamento de resultados
55
+
56
+ ### Regra geral
57
+
58
+ - Toda query deve ter um mapper explicito (funcao ou schema) que:
59
+ - valida shape (preferencialmente com Zod),
60
+ - converte tipos (INTEGER -> boolean, TEXT JSON -> objeto),
61
+ - normaliza campos opcionais.
62
+
63
+ ### Exemplo (conceitual)
64
+
65
+ - Query retorna `is_super_admin` (INTEGER).
66
+ - Mapper converte para boolean e retorna `isSuperAdmin`.
67
+ - Campo `provider_ids` (TEXT JSON) vira `string[]`.
68
+
69
+ ## Erros e tratamento
70
+
71
+ - `NotFoundError` quando `SELECT` nao retorna registros esperados.
72
+ - `ConflictError` quando violar unicidade (dominio/email/token).
73
+ - `ForbiddenError` para acesso indevido a `account_id`.
74
+ - Propagar erro de SQL com mensagem generica (evitar leak de detalhes).
75
+
76
+ ## Transacoes
77
+
78
+ - D1 nao oferece transacoes nativas. Operacoes multi-step devem ser planejadas
79
+ para serem idempotentes ou dividir em `batch` quando possivel.
80
+ - Para fluxos criticos, validar resultados intermediarios e registrar auditoria
81
+ com `transaction_id` compartilhado.
82
+
83
+ ## Auditoria
84
+
85
+ - Toda mutacao relevante deve registrar `audit_logs`.
86
+ - Usar `transaction_id` comum para agrupar operacoes.
87
+ - Registrar `changes` apenas com campos relevantes.
88
+
89
+ ## Checklist de migracao por modulo
90
+
91
+ - Listar queries atuais.
92
+ - Reescrever SQL com bind e filtros `account_id`/`deleted_at`.
93
+ - Adicionar mapper/validator.
94
+ - Atualizar testes afetados.
95
+
96
+ ## Referencias
97
+
98
+ - `docs/architecture/erd.md`
99
+ - `docs/architecture/data-requirements.md`
100
+ - `docs/architecture/drizzle-migration-plan.md`