@nebulit/embuilder 0.1.39

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 (212) hide show
  1. package/README.md +254 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +138 -0
  4. package/package.json +49 -0
  5. package/templates/.claude/hooks/QUICKSTART.md +256 -0
  6. package/templates/.claude/hooks/README.md +533 -0
  7. package/templates/.claude/hooks/analyze-commit.sh +22 -0
  8. package/templates/.claude/hooks/analyze-commit.ts +518 -0
  9. package/templates/.claude/hooks/analyzers/README.md +198 -0
  10. package/templates/.claude/hooks/analyzers/code-quality-checker.ts +154 -0
  11. package/templates/.claude/hooks/analyzers/code-quality.md +54 -0
  12. package/templates/.claude/hooks/analyzers/commit-blocker-example.ts.disabled +110 -0
  13. package/templates/.claude/hooks/analyzers/commit-policy.md +49 -0
  14. package/templates/.claude/hooks/analyzers/event-model-validator.md +49 -0
  15. package/templates/.claude/hooks/analyzers/event-model-validator.ts +169 -0
  16. package/templates/.claude/hooks/analyzers/example-logger.ts +70 -0
  17. package/templates/.claude/hooks/analyzers/slice-scope-validator.md +81 -0
  18. package/templates/.claude/hooks/check-review-result.sh +47 -0
  19. package/templates/.claude/hooks/prepare-review.sh +34 -0
  20. package/templates/.claude/hooks/review-agent-prompt.md +42 -0
  21. package/templates/.claude/hooks/run-review-agent.sh +124 -0
  22. package/templates/.claude/settings.local.json +37 -0
  23. package/templates/.claude/skills/help/README.md +84 -0
  24. package/templates/.claude/skills/help/SKILL.md +393 -0
  25. package/templates/.claude/skills/help/templates/demo-config.json +6753 -0
  26. package/templates/.claude/skills/sample-slices/SKILL.md +8 -0
  27. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/code-slice.json +124 -0
  28. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/slice.json +255 -0
  29. package/templates/.claude/skills/sample-slices/templates/.slices/Library/availablebooks/slice.json +107 -0
  30. package/templates/.claude/skills/sample-slices/templates/.slices/index.json +20 -0
  31. package/templates/.claude/skills/sample-slices/templates/Cart/additem/slice.json +979 -0
  32. package/templates/.claude/skills/sample-slices/templates/Cart/archiveitem/slice.json +529 -0
  33. package/templates/.claude/skills/sample-slices/templates/Cart/cartitems/slice.json +1072 -0
  34. package/templates/.claude/skills/sample-slices/templates/Cart/cartwithproducts/slice.json +394 -0
  35. package/templates/.claude/skills/sample-slices/templates/Cart/changedprices/slice.json +88 -0
  36. package/templates/.claude/skills/sample-slices/templates/Cart/changeinventory/slice.json +264 -0
  37. package/templates/.claude/skills/sample-slices/templates/Cart/changeprice/slice.json +308 -0
  38. package/templates/.claude/skills/sample-slices/templates/Cart/clearcart/slice.json +358 -0
  39. package/templates/.claude/skills/sample-slices/templates/Cart/inventories/slice.json +203 -0
  40. package/templates/.claude/skills/sample-slices/templates/Cart/publishcart/slice.json +876 -0
  41. package/templates/.claude/skills/sample-slices/templates/Cart/removeitem/slice.json +560 -0
  42. package/templates/.claude/skills/sample-slices/templates/Cart/submitcart/slice.json +708 -0
  43. package/templates/.claude/skills/sample-slices/templates/Cart/submittedcartdata/slice.json +399 -0
  44. package/templates/.claude/skills/sample-slices/templates/index.json +108 -0
  45. package/templates/.claude/skills/slice-automation/SKILL.md +49 -0
  46. package/templates/.claude/skills/slice-state-change/SKILL.md +369 -0
  47. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocation.test.ts.sample +76 -0
  48. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocationCommand.ts.sample +84 -0
  49. package/templates/.claude/skills/slice-state-change/templates/AddLocation/routes.ts.sample +73 -0
  50. package/templates/.claude/skills/slice-state-change/templates/README.md +46 -0
  51. package/templates/.claude/skills/slice-state-view/SKILL.md +336 -0
  52. package/templates/.claude/skills/slice-state-view/templates/Locations/Locations.test.ts.sample +84 -0
  53. package/templates/.claude/skills/slice-state-view/templates/Locations/LocationsProjection.ts.sample +50 -0
  54. package/templates/.claude/skills/slice-state-view/templates/Locations/routes.ts.sample +46 -0
  55. package/templates/.claude/skills/slice-state-view/templates/README.md +109 -0
  56. package/templates/.claude/skills/slice-state-view/templates/Tables/Tables.test.ts.sample +104 -0
  57. package/templates/.claude/skills/slice-state-view/templates/Tables/TablesProjection.ts.sample +59 -0
  58. package/templates/.claude/skills/slice-state-view/templates/Tables/routes.ts.sample +46 -0
  59. package/templates/.claude/skills/slice-state-view/templates/V2__tables.sql +7 -0
  60. package/templates/.claude/skills/slice-state-view/templates/V8__locations.sql +7 -0
  61. package/templates/.claude/skills/test-analyzer/SKILL.md +373 -0
  62. package/templates/.claude/skills/test-analyzer/examples/specification-format.md +143 -0
  63. package/templates/.claude/skills/test-analyzer/examples/state-change-example.md +111 -0
  64. package/templates/.claude/skills/test-analyzer/examples/state-view-example.md +122 -0
  65. package/templates/AGENTS.md +110 -0
  66. package/templates/Claude.md +58 -0
  67. package/templates/README.md +178 -0
  68. package/templates/backend/.env +9 -0
  69. package/templates/backend/BACKEND_AUTH_SETUP.md +183 -0
  70. package/templates/backend/SWAGGER.md +213 -0
  71. package/templates/backend/eslint.config.mjs +31 -0
  72. package/templates/backend/flyway.conf +17 -0
  73. package/templates/backend/package.json +44 -0
  74. package/templates/backend/prd.json.example +64 -0
  75. package/templates/backend/public/assets/images/banner.png +0 -0
  76. package/templates/backend/public/assets/logo.png +0 -0
  77. package/templates/backend/public/file.svg +4 -0
  78. package/templates/backend/public/globe.svg +12 -0
  79. package/templates/backend/public/next.svg +6 -0
  80. package/templates/backend/public/vercel.svg +3 -0
  81. package/templates/backend/public/window.svg +5 -0
  82. package/templates/backend/server.ts +129 -0
  83. package/templates/backend/setup-env.sh +50 -0
  84. package/templates/backend/src/common/assertions.ts +6 -0
  85. package/templates/backend/src/common/db.ts +1 -0
  86. package/templates/backend/src/common/loadPostgresEventstore.ts +16 -0
  87. package/templates/backend/src/common/parseEndpoint.ts +51 -0
  88. package/templates/backend/src/common/replay.ts +9 -0
  89. package/templates/backend/src/common/routes.ts +19 -0
  90. package/templates/backend/src/common/testHelpers.ts +53 -0
  91. package/templates/backend/src/core/readmodel.ts +28 -0
  92. package/templates/backend/src/core/types.ts +26 -0
  93. package/templates/backend/src/process/process.ts +53 -0
  94. package/templates/backend/src/supabase/LoginHandler.ts +36 -0
  95. package/templates/backend/src/supabase/ProtectedPageProps.ts +21 -0
  96. package/templates/backend/src/supabase/README.md +171 -0
  97. package/templates/backend/src/supabase/api.ts +63 -0
  98. package/templates/backend/src/supabase/authMiddleware.ts +53 -0
  99. package/templates/backend/src/supabase/component.ts +12 -0
  100. package/templates/backend/src/supabase/requireUser.ts +72 -0
  101. package/templates/backend/src/supabase/serverProps.ts +25 -0
  102. package/templates/backend/src/supabase/staticProps.ts +10 -0
  103. package/templates/backend/src/swagger.ts +34 -0
  104. package/templates/backend/src/util/assertions.ts +6 -0
  105. package/templates/backend/supabase/config.toml +295 -0
  106. package/templates/backend/supabase/migrations/20260121155918593_catalogentries.sql.sample +23 -0
  107. package/templates/backend/supabase/seed.sql +1 -0
  108. package/templates/backend/tsconfig.json +31 -0
  109. package/templates/frontend/.env.development +3 -0
  110. package/templates/frontend/AGENTS.md +7 -0
  111. package/templates/frontend/README.md +73 -0
  112. package/templates/frontend/components.json +20 -0
  113. package/templates/frontend/eslint.config.js +26 -0
  114. package/templates/frontend/index.html +18 -0
  115. package/templates/frontend/package-lock.json +8347 -0
  116. package/templates/frontend/package.json +94 -0
  117. package/templates/frontend/postcss.config.js +6 -0
  118. package/templates/frontend/public/favicon.ico +0 -0
  119. package/templates/frontend/public/logo.png +0 -0
  120. package/templates/frontend/public/placeholder.svg +1 -0
  121. package/templates/frontend/public/robots.txt +14 -0
  122. package/templates/frontend/src/App.css +42 -0
  123. package/templates/frontend/src/App.tsx +47 -0
  124. package/templates/frontend/src/components/NavLink.tsx +28 -0
  125. package/templates/frontend/src/components/ProtectedRoute.tsx +24 -0
  126. package/templates/frontend/src/components/calendar/Calendar.tsx +302 -0
  127. package/templates/frontend/src/components/layout/DashboardLayout.tsx +21 -0
  128. package/templates/frontend/src/components/layout/Header.tsx +45 -0
  129. package/templates/frontend/src/components/layout/Sidebar.tsx +82 -0
  130. package/templates/frontend/src/components/tables/ReservationTemplates.tsx +189 -0
  131. package/templates/frontend/src/components/ui/accordion.tsx +52 -0
  132. package/templates/frontend/src/components/ui/alert-dialog.tsx +104 -0
  133. package/templates/frontend/src/components/ui/alert.tsx +43 -0
  134. package/templates/frontend/src/components/ui/aspect-ratio.tsx +5 -0
  135. package/templates/frontend/src/components/ui/avatar.tsx +38 -0
  136. package/templates/frontend/src/components/ui/badge.tsx +29 -0
  137. package/templates/frontend/src/components/ui/breadcrumb.tsx +90 -0
  138. package/templates/frontend/src/components/ui/button.tsx +47 -0
  139. package/templates/frontend/src/components/ui/calendar.tsx +54 -0
  140. package/templates/frontend/src/components/ui/card.tsx +43 -0
  141. package/templates/frontend/src/components/ui/carousel.tsx +224 -0
  142. package/templates/frontend/src/components/ui/chart.tsx +303 -0
  143. package/templates/frontend/src/components/ui/checkbox.tsx +26 -0
  144. package/templates/frontend/src/components/ui/collapsible.tsx +9 -0
  145. package/templates/frontend/src/components/ui/command.tsx +132 -0
  146. package/templates/frontend/src/components/ui/context-menu.tsx +178 -0
  147. package/templates/frontend/src/components/ui/dialog.tsx +95 -0
  148. package/templates/frontend/src/components/ui/drawer.tsx +87 -0
  149. package/templates/frontend/src/components/ui/dropdown-menu.tsx +179 -0
  150. package/templates/frontend/src/components/ui/form.tsx +129 -0
  151. package/templates/frontend/src/components/ui/hover-card.tsx +27 -0
  152. package/templates/frontend/src/components/ui/input-otp.tsx +61 -0
  153. package/templates/frontend/src/components/ui/input.tsx +22 -0
  154. package/templates/frontend/src/components/ui/label.tsx +17 -0
  155. package/templates/frontend/src/components/ui/menubar.tsx +207 -0
  156. package/templates/frontend/src/components/ui/navigation-menu.tsx +120 -0
  157. package/templates/frontend/src/components/ui/pagination.tsx +81 -0
  158. package/templates/frontend/src/components/ui/popover.tsx +29 -0
  159. package/templates/frontend/src/components/ui/progress.tsx +23 -0
  160. package/templates/frontend/src/components/ui/radio-group.tsx +36 -0
  161. package/templates/frontend/src/components/ui/resizable.tsx +37 -0
  162. package/templates/frontend/src/components/ui/scroll-area.tsx +38 -0
  163. package/templates/frontend/src/components/ui/select.tsx +143 -0
  164. package/templates/frontend/src/components/ui/separator.tsx +20 -0
  165. package/templates/frontend/src/components/ui/sheet.tsx +107 -0
  166. package/templates/frontend/src/components/ui/sidebar.tsx +637 -0
  167. package/templates/frontend/src/components/ui/skeleton.tsx +7 -0
  168. package/templates/frontend/src/components/ui/slider.tsx +23 -0
  169. package/templates/frontend/src/components/ui/sonner.tsx +27 -0
  170. package/templates/frontend/src/components/ui/stat-card.tsx +44 -0
  171. package/templates/frontend/src/components/ui/switch.tsx +27 -0
  172. package/templates/frontend/src/components/ui/table.tsx +72 -0
  173. package/templates/frontend/src/components/ui/tabs.tsx +53 -0
  174. package/templates/frontend/src/components/ui/textarea.tsx +21 -0
  175. package/templates/frontend/src/components/ui/toast.tsx +111 -0
  176. package/templates/frontend/src/components/ui/toaster.tsx +24 -0
  177. package/templates/frontend/src/components/ui/toggle-group.tsx +49 -0
  178. package/templates/frontend/src/components/ui/toggle.tsx +37 -0
  179. package/templates/frontend/src/components/ui/tooltip.tsx +28 -0
  180. package/templates/frontend/src/components/ui/use-toast.ts +3 -0
  181. package/templates/frontend/src/contexts/AuthContext.tsx +94 -0
  182. package/templates/frontend/src/contexts/RefreshContext.tsx +236 -0
  183. package/templates/frontend/src/hooks/api/index.ts +2 -0
  184. package/templates/frontend/src/hooks/api/useLocations.ts +15 -0
  185. package/templates/frontend/src/hooks/use-mobile.tsx +19 -0
  186. package/templates/frontend/src/hooks/use-toast.ts +186 -0
  187. package/templates/frontend/src/hooks/useApiContext.ts +11 -0
  188. package/templates/frontend/src/index.css +118 -0
  189. package/templates/frontend/src/integrations/supabase/client.ts +9 -0
  190. package/templates/frontend/src/lib/api-client.ts +136 -0
  191. package/templates/frontend/src/lib/api.ts +1028 -0
  192. package/templates/frontend/src/lib/utils.ts +6 -0
  193. package/templates/frontend/src/main.tsx +5 -0
  194. package/templates/frontend/src/pages/Auth.tsx +408 -0
  195. package/templates/frontend/src/pages/Dashboard.tsx +168 -0
  196. package/templates/frontend/src/pages/Menus.tsx +224 -0
  197. package/templates/frontend/src/pages/NotFound.tsx +24 -0
  198. package/templates/frontend/src/pages/Register.tsx +285 -0
  199. package/templates/frontend/src/test/example.test.ts +0 -0
  200. package/templates/frontend/src/test/setup.ts +15 -0
  201. package/templates/frontend/src/types/index.ts +8 -0
  202. package/templates/frontend/src/vite-env.d.ts +1 -0
  203. package/templates/frontend/tailwind.config.ts +101 -0
  204. package/templates/frontend/tsconfig.app.json +31 -0
  205. package/templates/frontend/tsconfig.json +16 -0
  206. package/templates/frontend/tsconfig.node.json +22 -0
  207. package/templates/frontend/vite.config.ts +21 -0
  208. package/templates/frontend/vitest.config.ts +16 -0
  209. package/templates/init.sh +1 -0
  210. package/templates/prompt.md +139 -0
  211. package/templates/ralph.sh +120 -0
  212. package/templates/server.mjs +505 -0
@@ -0,0 +1,178 @@
1
+ # Event Model Project
2
+
3
+ This project uses event-model driven development with Claude Code and EMBuilder.
4
+
5
+ ## Quick Start
6
+
7
+ ### Available Commands
8
+
9
+ Use these commands in Claude Code to generate slices from your event model:
10
+
11
+ **Event Model Skills:**
12
+ ```
13
+ /state-change-slice # Generate a command handler slice
14
+ /state-view-slice # Generate a read model/projection slice
15
+ /automation-slice # Generate a background automation slice
16
+ ```
17
+
18
+ **Configuration:**
19
+ ```
20
+ /fetch-config # Fetch config.json from event model app (localhost:3001)
21
+ ```
22
+
23
+ **Yeoman Generator Skills:**
24
+ ```
25
+ /gen-skeleton # Generate Supabase backend skeleton app
26
+ /gen-state-change # Generate state change slices from config.json
27
+ /gen-state-view # Generate state view slices from config.json
28
+ /gen-automation # Generate automation slices from config.json
29
+ /gen-ui # Set up React UI with shadcn/ui and Supabase
30
+ ```
31
+
32
+ ## How to Invoke
33
+
34
+ ### Using Event Model Skills
35
+
36
+ 1. **Generate a State Change Slice (Command Handler)**
37
+ ```
38
+ In Claude Code, type: /state-change-slice
39
+ ```
40
+ Claude will:
41
+ - Find your event model file
42
+ - Ask you which command to implement
43
+ - Generate CommandHandler.ts with business logic
44
+ - Create routes.ts for HTTP endpoints
45
+ - Generate tests
46
+ - Run the tests automatically
47
+
48
+ 2. **Generate a State View Slice (Read Model)**
49
+ ```
50
+ In Claude Code, type: /state-view-slice
51
+ ```
52
+ Claude will:
53
+ - Find your event model
54
+ - Ask which read model to implement
55
+ - Generate Projection.ts with event handlers
56
+ - Create query endpoints
57
+ - Generate tests
58
+ - Run the tests
59
+
60
+ 3. **Generate an Automation Slice (Background Process)**
61
+ ```
62
+ In Claude Code, type: /automation-slice
63
+ ```
64
+ Claude will:
65
+ - Find your event model
66
+ - Ask which automation to implement
67
+ - Generate processor.ts with CRON logic
68
+ - Create background job handlers
69
+ - Generate tests
70
+ - Run the tests
71
+
72
+ ### Using Yeoman Generator Skills
73
+
74
+ 1. **Fetch Configuration from Event Model App**
75
+ ```
76
+ In Claude Code, type: /fetch-config
77
+ ```
78
+ This will start a server and fetch config.json from your running event model app.
79
+
80
+ 2. **Generate Multiple Slices from Config**
81
+ ```
82
+ In Claude Code, type: /gen-state-change
83
+ ```
84
+ Or use `/gen-state-view` or `/gen-automation` to generate slices based on your config.json.
85
+
86
+ 3. **Bootstrap a New Project**
87
+ ```
88
+ In Claude Code, type: /gen-skeleton
89
+ ```
90
+ This will create a complete Supabase backend skeleton.
91
+
92
+ 4. **Set Up UI**
93
+ ```
94
+ In Claude Code, type: /gen-ui
95
+ ```
96
+ This will scaffold a React UI with shadcn/ui and Supabase integration.
97
+
98
+ ## Project Structure
99
+
100
+ Your generated slices will follow this structure:
101
+
102
+ ```
103
+ src/slices/{slice-name}/
104
+ ├── CommandHandler.ts # Business logic (state-change slices)
105
+ ├── Projection.ts # Read model (state-view slices)
106
+ ├── processor.ts # CRON automation (automation slices)
107
+ ├── routes.ts # HTTP API endpoints
108
+ ├── {SliceName}.test.ts # Automated tests
109
+ └── ui/ # UI components (optional)
110
+ ```
111
+
112
+ ## Event Model Location
113
+
114
+ Make sure your event model JSON files are in one of these locations:
115
+ - `src/events/`
116
+ - `events/`
117
+ - Root directory
118
+
119
+ Claude Code will automatically find and read your event model.
120
+
121
+ ## Template Files
122
+
123
+ This project includes the following template files:
124
+
125
+ - **`Claude.md`** - Project-specific configuration for Claude Code
126
+ - **`AGENTS.md`** - Track learnings and patterns from development
127
+ - **`ralph.sh`** - Autonomous agent loop for continuous development
128
+ - **`prompt.md`** - Agent instructions for automated development
129
+
130
+ ## Development Workflow
131
+
132
+ 1. **Define your event model** in JSON format
133
+ 2. **Run a Claude skill** (e.g., `/state-change-slice`)
134
+ 3. **Claude generates the code** with tests
135
+ 4. **Tests run automatically** to verify correctness
136
+ 5. **Iterate** - modify the model and regenerate as needed
137
+
138
+ ## Autonomous Development with ralph.sh
139
+
140
+ Run the autonomous agent loop:
141
+
142
+ ```bash
143
+ ./ralph.sh
144
+ ```
145
+
146
+ This will:
147
+ - Read instructions from `prompt.md`
148
+ - Execute development tasks automatically
149
+ - Track learnings in `AGENTS.md`
150
+ - Continue until the task is complete
151
+
152
+ ## Need Help?
153
+
154
+ - Check the main EMBuilder documentation: https://github.com/dilgerma/embuilder
155
+ - Review the event model specifications in `src/events/`
156
+ - Ask Claude Code for guidance on any command
157
+
158
+ ## EMBuilder Commands
159
+
160
+ If you need to reinstall or update EMBuilder:
161
+
162
+ ```bash
163
+ # Install/update skills
164
+ npx @dilgerma/embuilder install
165
+
166
+ # Install with template files
167
+ npx @dilgerma/embuilder install --with-templates
168
+
169
+ # Check installation status
170
+ npx @dilgerma/embuilder status
171
+
172
+ # Uninstall
173
+ npx @dilgerma/embuilder uninstall
174
+ ```
175
+
176
+ ---
177
+
178
+ Generated by EMBuilder - Event-Model driven development for Claude Code
@@ -0,0 +1,9 @@
1
+ SUPABASE_URL=https://<project-id>.supabase.co
2
+ SUPABASE_PUBLISHABLE_KEY=<supabase-publishable-key>
3
+ SUPABASE_DB_URL=postgresql://postgres.<project-id>:<database.password>@aws-1-eu-central-1.pooler.supabase.com:5432/postgres?prepareThreshold=0
4
+ SUPABASE_SECRET_KEY=<supabase-secret-key>
5
+
6
+ # Flyway configuration
7
+ FLYWAY_URL=jdbc:postgresql://aws-1-eu-central-1.pooler.supabase.com:6543/postgres?prepareThreshold=0
8
+ FLYWAY_USER=postgres.<project-id>
9
+ FLYWAY_PASSWORD=<database.password>
@@ -0,0 +1,183 @@
1
+ # Backend JWT Authentication Setup - Summary
2
+
3
+ ## What Was Done
4
+
5
+ Your Express.js backend has been configured to use **JWT token authentication** instead of cookie-based sessions.
6
+
7
+ ### Changes Made
8
+
9
+ #### 1. **Removed Cookie-Based Auth**
10
+
11
+ - Removed `cookie-parser` from server.ts
12
+ - Removed OAuth callback route (`/api/auth/confirm`)
13
+ - Removed old cookie-based Supabase client setup
14
+
15
+ #### 2. **Added JWT Token Verification**
16
+
17
+ - **`src/supabase/api.ts`**: Stateless Supabase client for JWT verification
18
+ - **`src/supabase/requireUser.ts`**: Extracts and verifies JWT from `Authorization` header
19
+ - **`src/supabase/authMiddleware.ts`**: Express middleware for protecting routes
20
+ - **`src/supabase/component.ts`**: Browser client for test login page
21
+
22
+ #### 3. **Updated API Endpoints**
23
+
24
+ - **`GET /api/user`**: Now requires `Authorization: Bearer <token>` header
25
+ - Returns user info: `userId`, `email`, `metadata`
26
+
27
+ #### 4. **Frontend Cleanup**
28
+
29
+ - **Removed**: `register.tsx`, `reset-password.tsx`
30
+ - **Updated**: `login.tsx` → Simple test page that displays JWT token
31
+ - Access at: http://localhost:3000/auth/login
32
+
33
+ ---
34
+
35
+ ## How to Use
36
+
37
+ ### 1. Get a JWT Token
38
+
39
+ **Option A: Use Test Login Page**
40
+
41
+ 1. Start server: `npm run dev`
42
+ 2. Visit: http://localhost:3000/auth/login
43
+ 3. Create account or login
44
+ 4. Copy the JWT token displayed
45
+
46
+ **Option B: Get Token from Client**
47
+
48
+ ```javascript
49
+ const { data } = await supabase.auth.signInWithPassword({ email, password })
50
+ const token = data.session.access_token
51
+ ```
52
+
53
+ ### 2. Make Authenticated Requests
54
+
55
+ **Using cURL:**
56
+
57
+ ```bash
58
+ curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
59
+ http://localhost:3000/api/user
60
+ ```
61
+
62
+ **Using JavaScript fetch:**
63
+
64
+ ```javascript
65
+ fetch('/api/user', {
66
+ headers: {
67
+ 'Authorization': `Bearer ${token}`
68
+ }
69
+ })
70
+ .then(res => res.json())
71
+ .then(data => console.log(data))
72
+ ```
73
+
74
+ ### 3. Protect Your Routes
75
+
76
+ **Method 1: Using authMiddleware**
77
+
78
+ ```typescript
79
+ import {authMiddleware} from './src/supabase/authMiddleware'
80
+
81
+ app.get('/api/protected', authMiddleware, (req, res) => {
82
+ const user = (req as any).user
83
+ res.json({user})
84
+ })
85
+ ```
86
+
87
+ **Method 2: Using requireUser function**
88
+
89
+ ```typescript
90
+ import {requireUser} from './src/supabase/requireUser'
91
+
92
+ app.get('/api/protected', async (req, res) => {
93
+ const result = await requireUser(req, res, false)
94
+
95
+ if (result.error) {
96
+ return res.status(401).json({error: result.error})
97
+ }
98
+
99
+ const user = result.user
100
+ res.json({user})
101
+ })
102
+ ```
103
+
104
+ ---
105
+
106
+ ## File Structure
107
+
108
+ ```
109
+ src/supabase/
110
+ ├── api.ts # Supabase client creation
111
+ ├── requireUser.ts # JWT verification function
112
+ ├── authMiddleware.ts # Express middleware
113
+ ├── component.ts # Browser client (for test page)
114
+ ├── supabaseClient.ts # Environment constants
115
+ └── README.md # Complete documentation
116
+
117
+ src/pages/auth/
118
+ └── login.tsx # Test login page with JWT display
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Environment Variables
124
+
125
+ Add to `.env.local`:
126
+
127
+ ```env
128
+ NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
129
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
130
+ ```
131
+
132
+ ---
133
+
134
+ ## API Responses
135
+
136
+ ### Success (200)
137
+
138
+ ```json
139
+ {
140
+ "userId": "550e8400-e29b-41d4-a716-446655440000",
141
+ "email": "user@example.com",
142
+ "metadata": {
143
+ "name": "John Doe"
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### Unauthorized (401)
149
+
150
+ ```json
151
+ {
152
+ "error": "Missing authorization token"
153
+ }
154
+ ```
155
+
156
+ or
157
+
158
+ ```json
159
+ {
160
+ "error": "Invalid or expired token"
161
+ }
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Security Notes
167
+
168
+ ✅ JWT tokens are verified with Supabase on every request
169
+ ✅ No session storage on backend (stateless)
170
+ ✅ Tokens expire automatically
171
+ ⚠️ Always use HTTPS in production
172
+ ⚠️ Keep environment variables secure
173
+
174
+ ---
175
+
176
+ ## Next Steps
177
+
178
+ 1. Add your Supabase anon key to `.env.local`
179
+ 2. Use `authMiddleware` or `requireUser` in your slice routes
180
+ 3. Remove test login page in production if not needed
181
+ 4. Consider adding role-based authorization if needed
182
+
183
+ For complete documentation, see: `src/supabase/README.md`
@@ -0,0 +1,213 @@
1
+ # Swagger UI & OpenAPI Documentation
2
+
3
+ ## Overview
4
+
5
+ This project includes Swagger UI for interactive API documentation and OpenAPI specification generation.
6
+
7
+ ## Quick Start
8
+
9
+ 1. Start the development server:
10
+
11
+ ```bash
12
+ npm run dev
13
+ ```
14
+
15
+ 2. Open Swagger UI in your browser:
16
+
17
+ ```
18
+ http://localhost:3000/api-docs
19
+ ```
20
+
21
+ 3. View the OpenAPI JSON specification:
22
+
23
+ ```
24
+ http://localhost:3000/swagger.json
25
+ ```
26
+
27
+ ## Documentation
28
+
29
+ The API documentation is automatically generated from JSDoc comments in your route files using `swagger-jsdoc`.
30
+
31
+ ### Adding Documentation to Routes
32
+
33
+ Add JSDoc comments above your route handlers with OpenAPI/Swagger syntax:
34
+
35
+ ```typescript
36
+ /**
37
+ * @swagger
38
+ * /api/query/shifts-collection:
39
+ * get:
40
+ * summary: Get shifts collection
41
+ * description: Retrieve all shifts or a specific shift by ID
42
+ * tags:
43
+ * - Shifts
44
+ * parameters:
45
+ * - in: query
46
+ * name: _id
47
+ * schema:
48
+ * type: string
49
+ * description: Optional shift ID to fetch a specific shift
50
+ * responses:
51
+ * 200:
52
+ * description: Successfully retrieved shifts
53
+ * content:
54
+ * application/json:
55
+ * schema:
56
+ * type: array
57
+ * items:
58
+ * type: object
59
+ * 500:
60
+ * description: Server error
61
+ */
62
+ router.get('/api/query/shifts-collection', async (req, res) => {
63
+ // route implementation
64
+ });
65
+ ```
66
+
67
+ ### Common Swagger Components
68
+
69
+ #### Authentication (Bearer Token)
70
+
71
+ ```typescript
72
+ /**
73
+ * @swagger
74
+ * /api/protected-route:
75
+ * get:
76
+ * summary: Protected endpoint
77
+ * security:
78
+ * - bearerAuth: []
79
+ * responses:
80
+ * 200:
81
+ * description: Success
82
+ * 401:
83
+ * description: Unauthorized
84
+ */
85
+ router.get('/api/protected-route', (req, res) => {
86
+ // implementation
87
+ });
88
+ ```
89
+
90
+ #### POST Request with Body
91
+
92
+ ```typescript
93
+ /**
94
+ * @swagger
95
+ * /api/shifts:
96
+ * post:
97
+ * summary: Create a new shift
98
+ * tags:
99
+ * - Shifts
100
+ * requestBody:
101
+ * required: true
102
+ * content:
103
+ * application/json:
104
+ * schema:
105
+ * type: object
106
+ * properties:
107
+ * name:
108
+ * type: string
109
+ * start_time:
110
+ * type: string
111
+ * format: date-time
112
+ * end_time:
113
+ * type: string
114
+ * format: date-time
115
+ * responses:
116
+ * 201:
117
+ * description: Shift created successfully
118
+ * 400:
119
+ * description: Bad request
120
+ */
121
+ router.post('/api/shifts', (req, res) => {
122
+ // implementation
123
+ });
124
+ ```
125
+
126
+ #### Path Parameters
127
+
128
+ ```typescript
129
+ /**
130
+ * @swagger
131
+ * /api/shifts/{id}:
132
+ * get:
133
+ * summary: Get a specific shift
134
+ * parameters:
135
+ * - in: path
136
+ * name: id
137
+ * required: true
138
+ * schema:
139
+ * type: string
140
+ * description: Shift ID
141
+ * responses:
142
+ * 200:
143
+ * description: Shift found
144
+ * 404:
145
+ * description: Shift not found
146
+ */
147
+ router.get('/api/shifts/:id', (req, res) => {
148
+ // implementation
149
+ });
150
+ ```
151
+
152
+ ## File Locations
153
+
154
+ - **Swagger Configuration**: `src/swagger.ts`
155
+ - **Server Integration**: `server.ts` (lines 81-97)
156
+ - **Route Documentation**: Add to any route file in `src/slices/*/routes.ts`
157
+
158
+ ## Configuration
159
+
160
+ The Swagger configuration is in `src/swagger.ts`:
161
+
162
+ ```typescript
163
+ const options = {
164
+ definition: {
165
+ openapi: '3.0.0',
166
+ info: {
167
+ title: 'Context API',
168
+ version: '1.0.0',
169
+ description: 'Event-driven API...',
170
+ },
171
+ servers: [
172
+ {
173
+ url: 'http://localhost:3000',
174
+ description: 'Development server',
175
+ },
176
+ ],
177
+ },
178
+ apis: ['./src/slices/**/routes.ts'], // Auto-discovers routes
179
+ };
180
+ ```
181
+
182
+ ## Testing Your API
183
+
184
+ 1. **In Swagger UI**: Click "Try it out" button to test endpoints
185
+ 2. **With cURL**:
186
+
187
+ ```bash
188
+ curl http://localhost:3000/api/query/shifts-collection
189
+ ```
190
+
191
+ 3. **With Postman**: Import the OpenAPI spec from `/swagger.json`
192
+
193
+ ## OpenAPI Spec Export
194
+
195
+ Download the full OpenAPI specification:
196
+
197
+ ```bash
198
+ curl http://localhost:3000/swagger.json > openapi.json
199
+ ```
200
+
201
+ Use it with:
202
+
203
+ - [Swagger Editor](https://editor.swagger.io/)
204
+ - [OpenAPI Tools](https://openapi.tools/)
205
+ - [Postman](https://www.postman.com/)
206
+ - [ReDoc](https://redoc.ly/)
207
+
208
+ ## Resources
209
+
210
+ - [Swagger/OpenAPI Documentation](https://swagger.io/specification/)
211
+ - [swagger-jsdoc](https://github.com/Surnet/swagger-jsdoc)
212
+ - [swagger-ui-express](https://github.com/scottie1984/swagger-ui-express)
213
+ - [OpenAPI 3.0 Specification](https://spec.openapis.org/oas/v3.0.3)
@@ -0,0 +1,31 @@
1
+ import {dirname} from "path";
2
+ import {fileURLToPath} from "url";
3
+ import {FlatCompat} from "@eslint/eslintrc";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ const compat = new FlatCompat({
9
+ baseDirectory: __dirname,
10
+ });
11
+
12
+ const eslintConfig = [
13
+ ...compat.extends("next/core-web-vitals", "next/typescript"),
14
+ {
15
+ rules: {
16
+ "no-unused-vars": "off", // Disable unused variable warnings
17
+ "@typescript-eslint/no-unused-vars": "off", // Also disable the TypeScript-specific version
18
+ "@typescript-eslint/no-restricted-types": [
19
+ "error",
20
+ {
21
+ "extendDefaults": true,
22
+ "types": {
23
+ "{}": false
24
+ }
25
+ }
26
+ ]
27
+ },
28
+ },
29
+ ];
30
+
31
+ export default eslintConfig;
@@ -0,0 +1,17 @@
1
+ # Flyway configuration file
2
+ # Database connection from .env file
3
+ flyway.url=${FLYWAY_URL}
4
+ flyway.user=${FLYWAY_USER}
5
+ flyway.password=${FLYWAY_PASSWORD}
6
+
7
+ # Migration files location
8
+ flyway.locations=filesystem:./supabase/migrations
9
+
10
+ # Default schema (Flyway will create flyway_schema_history table here)
11
+ flyway.schemas=public
12
+
13
+ # Placeholder replacement
14
+ flyway.placeholderReplacement=false
15
+
16
+ # Validate on migrate
17
+ flyway.validateOnMigrate=true
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "project",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "flyway:migrate": "dotenv flyway migrate",
7
+ "dev": "node --env-file=.env --require ts-node/register server.ts",
8
+ "build": "tsc",
9
+ "start": "NODE_ENV=production node --env-file=.env --require ts-node/register server.ts",
10
+ "test": "tsx --test 'src/**/*.test.ts'"
11
+ },
12
+ "dependencies": {
13
+ "@event-driven-io/emmett": "^0.41.0",
14
+ "@event-driven-io/emmett-expressjs": "^0.41.0",
15
+ "@event-driven-io/emmett-postgresql": "^0.41.0",
16
+ "@supabase/ssr": "^0.6.1",
17
+ "@supabase/supabase-js": "^2.50.0",
18
+ "cookie-parser": "^1.4.7",
19
+ "cors": "^2.8.6",
20
+ "express": "^4.18.2",
21
+ "glob": "^11.0.3",
22
+ "knex": "^3.1.0",
23
+ "node-cron": "^4.2.1",
24
+ "pg": "^8.17.2",
25
+ "swagger-jsdoc": "^6.2.8",
26
+ "swagger-ui-express": "^5.0.1",
27
+ "url": "^0.11.4"
28
+ },
29
+ "devDependencies": {
30
+ "@eslint/eslintrc": "^3",
31
+ "@testcontainers/postgresql": "^11.0.3",
32
+ "@types/cors": "^2.8.19",
33
+ "@types/express": "^4.17.21",
34
+ "@types/node": "^20",
35
+ "@types/swagger-jsdoc": "^6.0.4",
36
+ "@types/swagger-ui-express": "^4.1.8",
37
+ "dotenv-cli": "^11.0.0",
38
+ "eslint": "^9",
39
+ "sql-formatter": "^15.7.0",
40
+ "ts-node": "^10.9.2",
41
+ "tsx": "^4.20.3",
42
+ "typescript": "^5"
43
+ }
44
+ }