@riligar/agents-kit 1.11.0 → 1.13.0
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.
- package/.agent/skills/riligar-dev-backend/SKILL.md +122 -87
- package/.agent/skills/riligar-dev-backend/references/elysia-basics.md +224 -0
- package/.agent/skills/riligar-dev-backend/references/elysia-lifecycle.md +268 -0
- package/.agent/skills/riligar-dev-backend/references/elysia-patterns.md +324 -0
- package/.agent/skills/riligar-dev-backend/references/elysia-plugins.md +202 -0
- package/.agent/skills/riligar-dev-backend/references/elysia-validation.md +247 -0
- package/.agent/skills/riligar-dev-stripe/SKILL.md +196 -91
- package/.agent/skills/riligar-dev-stripe/assets/stripe-client.js +422 -0
- package/.agent/skills/riligar-dev-stripe/assets/stripe-server.js +300 -0
- package/.agent/skills/riligar-dev-stripe/references/stripe-database.md +369 -0
- package/.agent/skills/riligar-dev-stripe/references/stripe-elysia.md +342 -0
- package/.agent/skills/riligar-dev-stripe/references/stripe-react.md +478 -0
- package/.agent/skills/riligar-dev-stripe/references/stripe-webhooks.md +376 -0
- package/package.json +1 -1
- package/.agent/skills/riligar-dev-backend/api-style.md +0 -42
- package/.agent/skills/riligar-dev-backend/auth.md +0 -24
- package/.agent/skills/riligar-dev-backend/documentation.md +0 -26
- package/.agent/skills/riligar-dev-backend/graphql.md +0 -41
- package/.agent/skills/riligar-dev-backend/rate-limiting.md +0 -31
- package/.agent/skills/riligar-dev-backend/response.md +0 -37
- package/.agent/skills/riligar-dev-backend/rest.md +0 -40
- package/.agent/skills/riligar-dev-backend/security-testing.md +0 -122
- package/.agent/skills/riligar-dev-backend/trpc.md +0 -41
- package/.agent/skills/riligar-dev-backend/versioning.md +0 -22
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: riligar-dev-backend
|
|
3
3
|
type: development
|
|
4
|
-
description:
|
|
4
|
+
description: Elysia backend development patterns for Bun. Use when building APIs, routes, plugins, validation, middleware, and error handling with Elysia framework.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Elysia Backend Development
|
|
8
8
|
|
|
9
|
-
>
|
|
10
|
-
> **Learn to THINK, not copy fixed patterns.**
|
|
11
|
-
|
|
12
|
-
---
|
|
9
|
+
> Build fast, type-safe APIs with Elysia + Bun.
|
|
13
10
|
|
|
14
11
|
## Mandatory Guidelines
|
|
15
12
|
|
|
@@ -17,84 +14,122 @@ description: API design principles and decision-making. REST vs GraphQL vs tRPC
|
|
|
17
14
|
> All work in this skill MUST adhere to:
|
|
18
15
|
>
|
|
19
16
|
> - @[.agent/skills/riligar-dev-clean-code] (Clean Code Standards)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
17
|
+
> - @[.agent/skills/riligar-tech-stack] (Tech Stack - Bun, Elysia, SQLite, Drizzle)
|
|
18
|
+
|
|
19
|
+
## Quick Reference
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
import { Elysia, t } from 'elysia'
|
|
23
|
+
|
|
24
|
+
const app = new Elysia()
|
|
25
|
+
.get('/', () => 'Hello Elysia')
|
|
26
|
+
.post('/users', ({ body }) => createUser(body), {
|
|
27
|
+
body: t.Object({
|
|
28
|
+
name: t.String(),
|
|
29
|
+
email: t.String({ format: 'email' })
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
.listen(3000)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Content Map
|
|
36
|
+
|
|
37
|
+
| File | Description | When to Read |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| [elysia-basics.md](references/elysia-basics.md) | Setup, routes, handlers, context | Starting new project |
|
|
40
|
+
| [elysia-plugins.md](references/elysia-plugins.md) | Plugins, guards, modular design | Organizing code |
|
|
41
|
+
| [elysia-validation.md](references/elysia-validation.md) | TypeBox validation (body, query, params) | Input validation |
|
|
42
|
+
| [elysia-lifecycle.md](references/elysia-lifecycle.md) | Hooks (onBeforeHandle, onError, etc.) | Middleware, auth checks |
|
|
43
|
+
| [elysia-patterns.md](references/elysia-patterns.md) | REST patterns, responses, pagination | API design |
|
|
44
|
+
|
|
45
|
+
## Project Structure
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
src/
|
|
49
|
+
├── index.js # Entry point
|
|
50
|
+
├── routes/
|
|
51
|
+
│ ├── index.js # Route aggregator
|
|
52
|
+
│ ├── users.js # User routes plugin
|
|
53
|
+
│ └── posts.js # Post routes plugin
|
|
54
|
+
├── services/
|
|
55
|
+
│ ├── user.js # Business logic
|
|
56
|
+
│ └── post.js
|
|
57
|
+
├── database/
|
|
58
|
+
│ ├── db.js # Drizzle connection
|
|
59
|
+
│ ├── schema.js # Drizzle schema
|
|
60
|
+
│ └── migrations/
|
|
61
|
+
└── middleware/
|
|
62
|
+
├── auth.js # Auth middleware
|
|
63
|
+
└── logger.js # Request logging
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Core Patterns
|
|
67
|
+
|
|
68
|
+
### Route Plugin
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
// routes/users.js
|
|
72
|
+
import { Elysia, t } from 'elysia'
|
|
73
|
+
import { getUserById, createUser } from '../services/user'
|
|
74
|
+
|
|
75
|
+
export const userRoutes = new Elysia({ prefix: '/users' })
|
|
76
|
+
.get('/', () => getAllUsers())
|
|
77
|
+
.get('/:id', ({ params }) => getUserById(params.id))
|
|
78
|
+
.post('/', ({ body }) => createUser(body), {
|
|
79
|
+
body: t.Object({
|
|
80
|
+
name: t.String({ minLength: 1 }),
|
|
81
|
+
email: t.String({ format: 'email' })
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Main App
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// index.js
|
|
90
|
+
import { Elysia } from 'elysia'
|
|
91
|
+
import { userRoutes } from './routes/users'
|
|
92
|
+
import { postRoutes } from './routes/posts'
|
|
93
|
+
|
|
94
|
+
const app = new Elysia()
|
|
95
|
+
.onError(({ error, set }) => {
|
|
96
|
+
console.error(error)
|
|
97
|
+
set.status = 500
|
|
98
|
+
return { error: 'Internal Server Error' }
|
|
99
|
+
})
|
|
100
|
+
.use(userRoutes)
|
|
101
|
+
.use(postRoutes)
|
|
102
|
+
.listen(3000)
|
|
103
|
+
|
|
104
|
+
console.log(`Server running at ${app.server?.url}`)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Related Skills
|
|
108
|
+
|
|
109
|
+
| Need | Skill |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| **Authentication** | @[.agent/skills/riligar-dev-auth-elysia] |
|
|
112
|
+
| **Database** | @[.agent/skills/riligar-dev-database] |
|
|
113
|
+
| **Tech Stack** | @[.agent/skills/riligar-tech-stack] |
|
|
114
|
+
| **Clean Code** | @[.agent/skills/riligar-dev-clean-code] |
|
|
115
|
+
| **Infrastructure** | @[.agent/skills/riligar-infrastructure] |
|
|
116
|
+
|
|
117
|
+
## Decision Checklist
|
|
118
|
+
|
|
119
|
+
Before building an API:
|
|
120
|
+
|
|
121
|
+
- [ ] Defined route structure and prefixes?
|
|
122
|
+
- [ ] Planned validation for all inputs?
|
|
123
|
+
- [ ] Error handling configured?
|
|
124
|
+
- [ ] Auth middleware needed? → Use `riligar-dev-auth-elysia`
|
|
125
|
+
- [ ] Database connection setup? → Use `riligar-dev-database`
|
|
126
|
+
|
|
127
|
+
## Anti-Patterns
|
|
128
|
+
|
|
129
|
+
| Don't | Do |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| Put business logic in handlers | Extract to `services/` |
|
|
132
|
+
| Skip input validation | Use TypeBox (`t.Object`) |
|
|
133
|
+
| Ignore error handling | Use `onError` lifecycle |
|
|
134
|
+
| Create monolithic files | Split into plugins |
|
|
135
|
+
| Use verbs in routes (`/getUser`) | Use nouns (`/users/:id`) |
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Elysia Basics
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun add elysia
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Minimal Server
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
import { Elysia } from 'elysia'
|
|
13
|
+
|
|
14
|
+
const app = new Elysia()
|
|
15
|
+
.get('/', () => 'Hello World')
|
|
16
|
+
.listen(3000)
|
|
17
|
+
|
|
18
|
+
console.log(`Server running at ${app.server?.url}`)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## HTTP Methods
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const app = new Elysia()
|
|
25
|
+
.get('/users', () => getUsers()) // Read
|
|
26
|
+
.post('/users', ({ body }) => create(body)) // Create
|
|
27
|
+
.put('/users/:id', ({ params, body }) => replace(params.id, body)) // Replace
|
|
28
|
+
.patch('/users/:id', ({ params, body }) => update(params.id, body)) // Update
|
|
29
|
+
.delete('/users/:id', ({ params }) => remove(params.id)) // Delete
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Context Object
|
|
33
|
+
|
|
34
|
+
Every handler receives a context object with request data:
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
app.post('/example', (ctx) => {
|
|
38
|
+
// Request data
|
|
39
|
+
ctx.body // Parsed request body
|
|
40
|
+
ctx.query // Query string (?key=value)
|
|
41
|
+
ctx.params // Path parameters (/:id)
|
|
42
|
+
ctx.headers // Request headers
|
|
43
|
+
ctx.cookie // Cookies
|
|
44
|
+
ctx.request // Raw Request object
|
|
45
|
+
ctx.path // Request pathname
|
|
46
|
+
|
|
47
|
+
// Response helpers
|
|
48
|
+
ctx.set.status = 201 // Set status code
|
|
49
|
+
ctx.set.headers['X-Custom'] = 'value' // Set header
|
|
50
|
+
ctx.redirect('/other') // Redirect
|
|
51
|
+
|
|
52
|
+
return { success: true }
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Destructuring Context
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
// Clean handler with destructuring
|
|
60
|
+
app.post('/users', ({ body, set }) => {
|
|
61
|
+
const user = createUser(body)
|
|
62
|
+
set.status = 201
|
|
63
|
+
return user
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
app.get('/users/:id', ({ params }) => {
|
|
67
|
+
return getUserById(params.id)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
app.get('/search', ({ query }) => {
|
|
71
|
+
return search(query.q, query.limit)
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Response Types
|
|
76
|
+
|
|
77
|
+
### JSON (default)
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
app.get('/json', () => {
|
|
81
|
+
return { message: 'Hello' } // Automatically JSON
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### String
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
app.get('/text', () => {
|
|
89
|
+
return 'Plain text response'
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Status Codes
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
app.post('/users', ({ body, set }) => {
|
|
97
|
+
const user = createUser(body)
|
|
98
|
+
set.status = 201 // Created
|
|
99
|
+
return user
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
app.get('/users/:id', ({ params, set }) => {
|
|
103
|
+
const user = findUser(params.id)
|
|
104
|
+
if (!user) {
|
|
105
|
+
set.status = 404
|
|
106
|
+
return { error: 'User not found' }
|
|
107
|
+
}
|
|
108
|
+
return user
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Redirect
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
app.get('/old-path', ({ redirect }) => {
|
|
116
|
+
return redirect('/new-path')
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Route Parameters
|
|
121
|
+
|
|
122
|
+
### Path Parameters
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// Single parameter
|
|
126
|
+
app.get('/users/:id', ({ params }) => {
|
|
127
|
+
return getUserById(params.id)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Multiple parameters
|
|
131
|
+
app.get('/users/:userId/posts/:postId', ({ params }) => {
|
|
132
|
+
return getPost(params.userId, params.postId)
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Query Parameters
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
// GET /search?q=hello&limit=10
|
|
140
|
+
app.get('/search', ({ query }) => {
|
|
141
|
+
const { q, limit = '10' } = query
|
|
142
|
+
return search(q, parseInt(limit))
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Headers
|
|
147
|
+
|
|
148
|
+
### Reading Headers
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
app.get('/protected', ({ headers, set }) => {
|
|
152
|
+
const token = headers.authorization
|
|
153
|
+
if (!token) {
|
|
154
|
+
set.status = 401
|
|
155
|
+
return { error: 'Unauthorized' }
|
|
156
|
+
}
|
|
157
|
+
return { message: 'Welcome' }
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Setting Headers
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
app.get('/api/data', ({ set }) => {
|
|
165
|
+
set.headers['X-Custom-Header'] = 'value'
|
|
166
|
+
set.headers['Cache-Control'] = 'max-age=3600'
|
|
167
|
+
return { data: 'example' }
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Cookies
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
app.get('/set-cookie', ({ cookie }) => {
|
|
175
|
+
cookie.session.set({
|
|
176
|
+
value: 'abc123',
|
|
177
|
+
httpOnly: true,
|
|
178
|
+
maxAge: 60 * 60 * 24 // 1 day
|
|
179
|
+
})
|
|
180
|
+
return { message: 'Cookie set' }
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
app.get('/read-cookie', ({ cookie }) => {
|
|
184
|
+
return { session: cookie.session.value }
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Static Files
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
import { Elysia } from 'elysia'
|
|
192
|
+
import { staticPlugin } from '@elysiajs/static'
|
|
193
|
+
|
|
194
|
+
const app = new Elysia()
|
|
195
|
+
.use(staticPlugin({
|
|
196
|
+
prefix: '/public',
|
|
197
|
+
assets: 'public'
|
|
198
|
+
}))
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Environment Variables
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// Use Bun's built-in env
|
|
205
|
+
const port = process.env.PORT || 3000
|
|
206
|
+
const dbUrl = process.env.DATABASE_URL
|
|
207
|
+
|
|
208
|
+
const app = new Elysia()
|
|
209
|
+
.listen(port)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Graceful Shutdown
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
const app = new Elysia()
|
|
216
|
+
.get('/', () => 'Hello')
|
|
217
|
+
.listen(3000)
|
|
218
|
+
|
|
219
|
+
process.on('SIGINT', () => {
|
|
220
|
+
console.log('Shutting down...')
|
|
221
|
+
app.stop()
|
|
222
|
+
process.exit(0)
|
|
223
|
+
})
|
|
224
|
+
```
|