@mytechtoday/augment-extensions 0.1.0 → 0.1.1
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/AGENTS.md +83 -3
- package/README.md +6 -5
- package/augment-extensions/coding-standards/python/README.md +44 -0
- package/augment-extensions/coding-standards/python/module.json +26 -0
- package/augment-extensions/coding-standards/python/rules/best-practices.md +232 -0
- package/augment-extensions/coding-standards/python/rules/code-organization.md +220 -0
- package/augment-extensions/coding-standards/python/rules/error-handling.md +221 -0
- package/augment-extensions/coding-standards/python/rules/naming-conventions.md +172 -0
- package/augment-extensions/coding-standards/python/rules/type-hints.md +188 -0
- package/augment-extensions/coding-standards/react/README.md +45 -0
- package/augment-extensions/coding-standards/react/module.json +27 -0
- package/augment-extensions/coding-standards/react/rules/component-patterns.md +214 -0
- package/augment-extensions/coding-standards/react/rules/hooks-best-practices.md +235 -0
- package/augment-extensions/coding-standards/react/rules/performance.md +300 -0
- package/augment-extensions/coding-standards/react/rules/state-management.md +265 -0
- package/augment-extensions/coding-standards/react/rules/typescript-react.md +271 -0
- package/augment-extensions/domain-rules/api-design/README.md +41 -0
- package/augment-extensions/domain-rules/api-design/module.json +27 -0
- package/augment-extensions/domain-rules/api-design/rules/authentication.md +263 -0
- package/augment-extensions/domain-rules/api-design/rules/documentation.md +395 -0
- package/augment-extensions/domain-rules/api-design/rules/error-handling.md +290 -0
- package/augment-extensions/domain-rules/api-design/rules/graphql-api.md +313 -0
- package/augment-extensions/domain-rules/api-design/rules/rest-api.md +214 -0
- package/augment-extensions/domain-rules/api-design/rules/versioning.md +268 -0
- package/augment-extensions/domain-rules/security/README.md +41 -0
- package/augment-extensions/domain-rules/security/module.json +28 -0
- package/augment-extensions/domain-rules/security/rules/authentication-security.md +361 -0
- package/augment-extensions/domain-rules/security/rules/encryption.md +208 -0
- package/augment-extensions/domain-rules/security/rules/input-validation.md +294 -0
- package/augment-extensions/domain-rules/security/rules/owasp-top-10.md +339 -0
- package/augment-extensions/domain-rules/security/rules/secure-coding.md +293 -0
- package/augment-extensions/domain-rules/security/rules/web-security.md +268 -0
- package/augment-extensions/examples/design-patterns/README.md +37 -0
- package/augment-extensions/examples/design-patterns/examples/behavioral-patterns.md +370 -0
- package/augment-extensions/examples/design-patterns/examples/creational-patterns.md +250 -0
- package/augment-extensions/examples/design-patterns/examples/structural-patterns.md +264 -0
- package/augment-extensions/examples/design-patterns/module.json +27 -0
- package/{modules → augment-extensions}/workflows/beads/examples/complete-workflow-example.md +5 -5
- package/{modules → augment-extensions}/workflows/beads/rules/file-format.md +45 -1
- package/{modules → augment-extensions}/workflows/beads/rules/workflow.md +41 -0
- package/{modules → augment-extensions}/workflows/openspec/examples/complete-change-example.md +14 -0
- package/{modules → augment-extensions}/workflows/openspec/rules/spec-format.md +44 -1
- package/{modules → augment-extensions}/workflows/openspec/rules/workflow.md +25 -0
- package/cli/dist/cli.js +64 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/coord.d.ts +30 -0
- package/cli/dist/commands/coord.d.ts.map +1 -0
- package/cli/dist/commands/coord.js +150 -0
- package/cli/dist/commands/coord.js.map +1 -0
- package/cli/dist/commands/link.js +1 -1
- package/cli/dist/commands/link.js.map +1 -1
- package/cli/dist/commands/list.js +1 -1
- package/cli/dist/commands/list.js.map +1 -1
- package/cli/dist/commands/search.d.ts.map +1 -1
- package/cli/dist/commands/search.js +107 -5
- package/cli/dist/commands/search.js.map +1 -1
- package/cli/dist/commands/show.js +1 -1
- package/cli/dist/commands/show.js.map +1 -1
- package/cli/dist/commands/sync.d.ts +26 -0
- package/cli/dist/commands/sync.d.ts.map +1 -0
- package/cli/dist/commands/sync.js +106 -0
- package/cli/dist/commands/sync.js.map +1 -0
- package/cli/dist/commands/update.d.ts.map +1 -1
- package/cli/dist/commands/update.js +132 -7
- package/cli/dist/commands/update.js.map +1 -1
- package/cli/dist/utils/auto-sync.d.ts +34 -0
- package/cli/dist/utils/auto-sync.d.ts.map +1 -0
- package/cli/dist/utils/auto-sync.js +172 -0
- package/cli/dist/utils/auto-sync.js.map +1 -0
- package/cli/dist/utils/beads-sync.d.ts +51 -0
- package/cli/dist/utils/beads-sync.d.ts.map +1 -0
- package/cli/dist/utils/beads-sync.js +171 -0
- package/cli/dist/utils/beads-sync.js.map +1 -0
- package/cli/dist/utils/coordination-queries.d.ts +79 -0
- package/cli/dist/utils/coordination-queries.d.ts.map +1 -0
- package/cli/dist/utils/coordination-queries.js +155 -0
- package/cli/dist/utils/coordination-queries.js.map +1 -0
- package/cli/dist/utils/file-tracking.d.ts +42 -0
- package/cli/dist/utils/file-tracking.d.ts.map +1 -0
- package/cli/dist/utils/file-tracking.js +155 -0
- package/cli/dist/utils/file-tracking.js.map +1 -0
- package/cli/dist/utils/migrate.d.ts +25 -0
- package/cli/dist/utils/migrate.d.ts.map +1 -0
- package/cli/dist/utils/migrate.js +204 -0
- package/cli/dist/utils/migrate.js.map +1 -0
- package/cli/dist/utils/openspec-sync.d.ts +48 -0
- package/cli/dist/utils/openspec-sync.d.ts.map +1 -0
- package/cli/dist/utils/openspec-sync.js +167 -0
- package/cli/dist/utils/openspec-sync.js.map +1 -0
- package/{MODULES.md → modules.md} +1 -1
- package/package.json +9 -7
- /package/{modules → augment-extensions}/coding-standards/typescript/README.md +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/module.json +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/rules/naming-conventions.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/manual-setup.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/manual-setup.md +0 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# GraphQL API Design
|
|
2
|
+
|
|
3
|
+
Best practices for designing GraphQL APIs.
|
|
4
|
+
|
|
5
|
+
## Schema Design
|
|
6
|
+
|
|
7
|
+
Design clear, intuitive schemas.
|
|
8
|
+
|
|
9
|
+
```graphql
|
|
10
|
+
# Good - Clear type definitions
|
|
11
|
+
type User {
|
|
12
|
+
id: ID!
|
|
13
|
+
name: String!
|
|
14
|
+
email: String!
|
|
15
|
+
role: UserRole!
|
|
16
|
+
createdAt: DateTime!
|
|
17
|
+
orders: [Order!]!
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type Order {
|
|
21
|
+
id: ID!
|
|
22
|
+
user: User!
|
|
23
|
+
items: [OrderItem!]!
|
|
24
|
+
total: Float!
|
|
25
|
+
status: OrderStatus!
|
|
26
|
+
createdAt: DateTime!
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
enum UserRole {
|
|
30
|
+
ADMIN
|
|
31
|
+
USER
|
|
32
|
+
GUEST
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
enum OrderStatus {
|
|
36
|
+
PENDING
|
|
37
|
+
PROCESSING
|
|
38
|
+
SHIPPED
|
|
39
|
+
DELIVERED
|
|
40
|
+
CANCELLED
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Good - Input types for mutations
|
|
44
|
+
input CreateUserInput {
|
|
45
|
+
name: String!
|
|
46
|
+
email: String!
|
|
47
|
+
role: UserRole = USER
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
input UpdateUserInput {
|
|
51
|
+
name: String
|
|
52
|
+
email: String
|
|
53
|
+
role: UserRole
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Queries
|
|
58
|
+
|
|
59
|
+
Design efficient, flexible queries.
|
|
60
|
+
|
|
61
|
+
```graphql
|
|
62
|
+
# Good - Root queries
|
|
63
|
+
type Query {
|
|
64
|
+
# Single resource
|
|
65
|
+
user(id: ID!): User
|
|
66
|
+
|
|
67
|
+
# Collection with filtering
|
|
68
|
+
users(
|
|
69
|
+
role: UserRole
|
|
70
|
+
status: UserStatus
|
|
71
|
+
limit: Int = 20
|
|
72
|
+
offset: Int = 0
|
|
73
|
+
): UserConnection!
|
|
74
|
+
|
|
75
|
+
# Search
|
|
76
|
+
searchUsers(query: String!): [User!]!
|
|
77
|
+
|
|
78
|
+
# Nested resource
|
|
79
|
+
order(id: ID!): Order
|
|
80
|
+
orders(userId: ID, status: OrderStatus): [Order!]!
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Good - Connection pattern for pagination
|
|
84
|
+
type UserConnection {
|
|
85
|
+
edges: [UserEdge!]!
|
|
86
|
+
pageInfo: PageInfo!
|
|
87
|
+
totalCount: Int!
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type UserEdge {
|
|
91
|
+
node: User!
|
|
92
|
+
cursor: String!
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
type PageInfo {
|
|
96
|
+
hasNextPage: Boolean!
|
|
97
|
+
hasPreviousPage: Boolean!
|
|
98
|
+
startCursor: String
|
|
99
|
+
endCursor: String
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Mutations
|
|
104
|
+
|
|
105
|
+
Design clear, atomic mutations.
|
|
106
|
+
|
|
107
|
+
```graphql
|
|
108
|
+
# Good - Mutations with input types
|
|
109
|
+
type Mutation {
|
|
110
|
+
createUser(input: CreateUserInput!): CreateUserPayload!
|
|
111
|
+
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
|
|
112
|
+
deleteUser(id: ID!): DeleteUserPayload!
|
|
113
|
+
|
|
114
|
+
createOrder(input: CreateOrderInput!): CreateOrderPayload!
|
|
115
|
+
updateOrderStatus(id: ID!, status: OrderStatus!): UpdateOrderPayload!
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Good - Payload types with errors
|
|
119
|
+
type CreateUserPayload {
|
|
120
|
+
user: User
|
|
121
|
+
errors: [UserError!]!
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type UserError {
|
|
125
|
+
field: String
|
|
126
|
+
message: String!
|
|
127
|
+
code: ErrorCode!
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
enum ErrorCode {
|
|
131
|
+
VALIDATION_ERROR
|
|
132
|
+
NOT_FOUND
|
|
133
|
+
UNAUTHORIZED
|
|
134
|
+
FORBIDDEN
|
|
135
|
+
INTERNAL_ERROR
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# Bad - Multiple operations in one mutation
|
|
139
|
+
type Mutation {
|
|
140
|
+
updateUserAndOrders(userId: ID!, userData: UpdateUserInput!, orderIds: [ID!]!): User
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Subscriptions
|
|
145
|
+
|
|
146
|
+
Design real-time subscriptions.
|
|
147
|
+
|
|
148
|
+
```graphql
|
|
149
|
+
# Good - Subscriptions for real-time updates
|
|
150
|
+
type Subscription {
|
|
151
|
+
userCreated: User!
|
|
152
|
+
userUpdated(id: ID!): User!
|
|
153
|
+
orderStatusChanged(userId: ID!): Order!
|
|
154
|
+
|
|
155
|
+
# With filtering
|
|
156
|
+
orderUpdated(status: OrderStatus): Order!
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Usage
|
|
160
|
+
subscription {
|
|
161
|
+
orderStatusChanged(userId: "123") {
|
|
162
|
+
id
|
|
163
|
+
status
|
|
164
|
+
updatedAt
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Field Naming
|
|
170
|
+
|
|
171
|
+
Use consistent naming conventions.
|
|
172
|
+
|
|
173
|
+
```graphql
|
|
174
|
+
# Good - Consistent naming
|
|
175
|
+
type User {
|
|
176
|
+
id: ID! # Singular
|
|
177
|
+
firstName: String! # camelCase
|
|
178
|
+
lastName: String!
|
|
179
|
+
emailAddress: String!
|
|
180
|
+
isActive: Boolean! # Boolean prefix: is, has, can
|
|
181
|
+
hasOrders: Boolean!
|
|
182
|
+
createdAt: DateTime! # Timestamp suffix: At
|
|
183
|
+
updatedAt: DateTime!
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Bad - Inconsistent naming
|
|
187
|
+
type User {
|
|
188
|
+
user_id: ID! # snake_case (inconsistent)
|
|
189
|
+
first_name: String!
|
|
190
|
+
active: Boolean! # Missing 'is' prefix
|
|
191
|
+
created: DateTime! # Missing 'At' suffix
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Error Handling
|
|
196
|
+
|
|
197
|
+
Implement comprehensive error handling.
|
|
198
|
+
|
|
199
|
+
```graphql
|
|
200
|
+
# Good - Errors in payload
|
|
201
|
+
type CreateUserPayload {
|
|
202
|
+
user: User
|
|
203
|
+
errors: [UserError!]!
|
|
204
|
+
success: Boolean!
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# Good - Field-level errors
|
|
208
|
+
type UserError {
|
|
209
|
+
field: String # Which field caused the error
|
|
210
|
+
message: String! # Human-readable message
|
|
211
|
+
code: ErrorCode! # Machine-readable code
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
# Usage in resolver
|
|
215
|
+
{
|
|
216
|
+
"data": {
|
|
217
|
+
"createUser": {
|
|
218
|
+
"user": null,
|
|
219
|
+
"errors": [
|
|
220
|
+
{
|
|
221
|
+
"field": "email",
|
|
222
|
+
"message": "Email is already taken",
|
|
223
|
+
"code": "VALIDATION_ERROR"
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
"success": false
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## N+1 Problem
|
|
233
|
+
|
|
234
|
+
Solve N+1 queries with DataLoader.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// Good - Use DataLoader
|
|
238
|
+
import DataLoader from 'dataloader';
|
|
239
|
+
|
|
240
|
+
const userLoader = new DataLoader(async (userIds: string[]) => {
|
|
241
|
+
const users = await db.users.findMany({
|
|
242
|
+
where: { id: { in: userIds } }
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return userIds.map(id => users.find(u => u.id === id));
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Resolver
|
|
249
|
+
const resolvers = {
|
|
250
|
+
Order: {
|
|
251
|
+
user: (order) => userLoader.load(order.userId)
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// Bad - N+1 query
|
|
256
|
+
const resolvers = {
|
|
257
|
+
Order: {
|
|
258
|
+
user: (order) => db.users.findOne({ id: order.userId })
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Pagination
|
|
264
|
+
|
|
265
|
+
Implement cursor-based pagination.
|
|
266
|
+
|
|
267
|
+
```graphql
|
|
268
|
+
# Good - Relay-style cursor pagination
|
|
269
|
+
type Query {
|
|
270
|
+
users(
|
|
271
|
+
first: Int
|
|
272
|
+
after: String
|
|
273
|
+
last: Int
|
|
274
|
+
before: String
|
|
275
|
+
): UserConnection!
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
# Usage
|
|
279
|
+
query {
|
|
280
|
+
users(first: 10, after: "cursor123") {
|
|
281
|
+
edges {
|
|
282
|
+
node {
|
|
283
|
+
id
|
|
284
|
+
name
|
|
285
|
+
}
|
|
286
|
+
cursor
|
|
287
|
+
}
|
|
288
|
+
pageInfo {
|
|
289
|
+
hasNextPage
|
|
290
|
+
endCursor
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Best Practices
|
|
297
|
+
|
|
298
|
+
1. **Use nullable fields carefully** - Only make required fields non-null
|
|
299
|
+
2. **Design for clients** - Think about client use cases
|
|
300
|
+
3. **Use input types** - For mutations
|
|
301
|
+
4. **Use payload types** - Include errors in mutation responses
|
|
302
|
+
5. **Solve N+1 problem** - Use DataLoader
|
|
303
|
+
6. **Implement pagination** - Use cursor-based pagination
|
|
304
|
+
7. **Version with fields** - Add new fields, deprecate old ones
|
|
305
|
+
8. **Use enums** - For fixed sets of values
|
|
306
|
+
9. **Document schema** - Use descriptions
|
|
307
|
+
10. **Validate input** - Server-side validation
|
|
308
|
+
11. **Implement auth** - Field-level authorization
|
|
309
|
+
12. **Monitor performance** - Track query complexity
|
|
310
|
+
13. **Use subscriptions** - For real-time updates
|
|
311
|
+
14. **Keep mutations atomic** - One operation per mutation
|
|
312
|
+
15. **Use consistent naming** - camelCase for fields
|
|
313
|
+
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# RESTful API Design
|
|
2
|
+
|
|
3
|
+
Best practices for designing RESTful APIs.
|
|
4
|
+
|
|
5
|
+
## Resource Naming
|
|
6
|
+
|
|
7
|
+
Use nouns for resources, not verbs.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
# Good - Nouns
|
|
11
|
+
GET /users
|
|
12
|
+
GET /users/123
|
|
13
|
+
POST /users
|
|
14
|
+
PUT /users/123
|
|
15
|
+
DELETE /users/123
|
|
16
|
+
|
|
17
|
+
GET /users/123/orders
|
|
18
|
+
POST /users/123/orders
|
|
19
|
+
|
|
20
|
+
# Bad - Verbs
|
|
21
|
+
GET /getUsers
|
|
22
|
+
POST /createUser
|
|
23
|
+
POST /deleteUser/123
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## HTTP Methods
|
|
27
|
+
|
|
28
|
+
Use appropriate HTTP methods for operations.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
GET - Retrieve resource(s) (safe, idempotent)
|
|
32
|
+
POST - Create new resource (not idempotent)
|
|
33
|
+
PUT - Update/replace entire resource (idempotent)
|
|
34
|
+
PATCH - Partial update of resource (idempotent)
|
|
35
|
+
DELETE - Remove resource (idempotent)
|
|
36
|
+
HEAD - Get headers only (safe, idempotent)
|
|
37
|
+
OPTIONS - Get available methods (safe, idempotent)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## URL Structure
|
|
41
|
+
|
|
42
|
+
Keep URLs simple, intuitive, and hierarchical.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
# Good - Clear hierarchy
|
|
46
|
+
GET /api/v1/users/123/orders/456/items
|
|
47
|
+
|
|
48
|
+
# Good - Query parameters for filtering
|
|
49
|
+
GET /api/v1/users?role=admin&status=active
|
|
50
|
+
|
|
51
|
+
# Good - Pagination
|
|
52
|
+
GET /api/v1/users?page=2&limit=20
|
|
53
|
+
|
|
54
|
+
# Bad - Deep nesting
|
|
55
|
+
GET /api/v1/users/123/orders/456/items/789/reviews/012
|
|
56
|
+
|
|
57
|
+
# Bad - Actions in URL
|
|
58
|
+
POST /api/v1/users/123/activate
|
|
59
|
+
# Better: PATCH /api/v1/users/123 with {"status": "active"}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## HTTP Status Codes
|
|
63
|
+
|
|
64
|
+
Use appropriate status codes.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
# Success
|
|
68
|
+
200 OK - Successful GET, PUT, PATCH, DELETE
|
|
69
|
+
201 Created - Successful POST (resource created)
|
|
70
|
+
204 No Content - Successful DELETE (no response body)
|
|
71
|
+
|
|
72
|
+
# Client Errors
|
|
73
|
+
400 Bad Request - Invalid request data
|
|
74
|
+
401 Unauthorized - Authentication required
|
|
75
|
+
403 Forbidden - Authenticated but not authorized
|
|
76
|
+
404 Not Found - Resource doesn't exist
|
|
77
|
+
409 Conflict - Resource conflict (e.g., duplicate)
|
|
78
|
+
422 Unprocessable - Validation errors
|
|
79
|
+
429 Too Many Requests - Rate limit exceeded
|
|
80
|
+
|
|
81
|
+
# Server Errors
|
|
82
|
+
500 Internal Server Error - Server error
|
|
83
|
+
502 Bad Gateway - Upstream server error
|
|
84
|
+
503 Service Unavailable - Server temporarily unavailable
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Request/Response Format
|
|
88
|
+
|
|
89
|
+
Use consistent JSON structure.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
// Good - GET /api/v1/users/123
|
|
93
|
+
{
|
|
94
|
+
"id": "123",
|
|
95
|
+
"name": "John Doe",
|
|
96
|
+
"email": "john@example.com",
|
|
97
|
+
"createdAt": "2024-01-15T10:30:00Z",
|
|
98
|
+
"updatedAt": "2024-01-20T14:45:00Z"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Good - POST /api/v1/users (request)
|
|
102
|
+
{
|
|
103
|
+
"name": "Jane Smith",
|
|
104
|
+
"email": "jane@example.com",
|
|
105
|
+
"role": "admin"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Good - POST /api/v1/users (response)
|
|
109
|
+
{
|
|
110
|
+
"id": "124",
|
|
111
|
+
"name": "Jane Smith",
|
|
112
|
+
"email": "jane@example.com",
|
|
113
|
+
"role": "admin",
|
|
114
|
+
"createdAt": "2024-01-21T09:00:00Z"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Good - Collection response
|
|
118
|
+
{
|
|
119
|
+
"data": [
|
|
120
|
+
{ "id": "123", "name": "John Doe" },
|
|
121
|
+
{ "id": "124", "name": "Jane Smith" }
|
|
122
|
+
],
|
|
123
|
+
"meta": {
|
|
124
|
+
"total": 100,
|
|
125
|
+
"page": 1,
|
|
126
|
+
"limit": 20,
|
|
127
|
+
"totalPages": 5
|
|
128
|
+
},
|
|
129
|
+
"links": {
|
|
130
|
+
"self": "/api/v1/users?page=1",
|
|
131
|
+
"next": "/api/v1/users?page=2",
|
|
132
|
+
"last": "/api/v1/users?page=5"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Error Responses
|
|
138
|
+
|
|
139
|
+
Provide consistent, helpful error messages.
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
// Good - Detailed error response
|
|
143
|
+
{
|
|
144
|
+
"error": {
|
|
145
|
+
"code": "VALIDATION_ERROR",
|
|
146
|
+
"message": "Validation failed",
|
|
147
|
+
"details": [
|
|
148
|
+
{
|
|
149
|
+
"field": "email",
|
|
150
|
+
"message": "Email is required"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"field": "age",
|
|
154
|
+
"message": "Age must be at least 18"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"timestamp": "2024-01-21T10:00:00Z",
|
|
158
|
+
"path": "/api/v1/users"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Good - Simple error
|
|
163
|
+
{
|
|
164
|
+
"error": {
|
|
165
|
+
"code": "NOT_FOUND",
|
|
166
|
+
"message": "User not found",
|
|
167
|
+
"timestamp": "2024-01-21T10:00:00Z"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Filtering, Sorting, Pagination
|
|
173
|
+
|
|
174
|
+
Support common query operations.
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
# Filtering
|
|
178
|
+
GET /api/v1/users?role=admin&status=active
|
|
179
|
+
|
|
180
|
+
# Sorting
|
|
181
|
+
GET /api/v1/users?sort=name
|
|
182
|
+
GET /api/v1/users?sort=-createdAt # Descending
|
|
183
|
+
|
|
184
|
+
# Pagination (offset-based)
|
|
185
|
+
GET /api/v1/users?page=2&limit=20
|
|
186
|
+
|
|
187
|
+
# Pagination (cursor-based)
|
|
188
|
+
GET /api/v1/users?cursor=abc123&limit=20
|
|
189
|
+
|
|
190
|
+
# Field selection
|
|
191
|
+
GET /api/v1/users?fields=id,name,email
|
|
192
|
+
|
|
193
|
+
# Search
|
|
194
|
+
GET /api/v1/users?q=john
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Best Practices
|
|
198
|
+
|
|
199
|
+
1. **Use nouns** - Resources are nouns, not verbs
|
|
200
|
+
2. **Use plural names** - `/users` not `/user`
|
|
201
|
+
3. **Use HTTP methods** - Don't put actions in URLs
|
|
202
|
+
4. **Use proper status codes** - Be specific and consistent
|
|
203
|
+
5. **Version your API** - `/api/v1/users`
|
|
204
|
+
6. **Use JSON** - Standard format for requests/responses
|
|
205
|
+
7. **Support pagination** - For collections
|
|
206
|
+
8. **Provide filtering** - Allow clients to filter data
|
|
207
|
+
9. **Use HATEOAS** - Include links in responses (optional)
|
|
208
|
+
10. **Document everything** - Use OpenAPI/Swagger
|
|
209
|
+
11. **Use ISO 8601** - For dates and times
|
|
210
|
+
12. **Use snake_case or camelCase** - Be consistent
|
|
211
|
+
13. **Validate input** - Return 422 for validation errors
|
|
212
|
+
14. **Rate limit** - Protect your API
|
|
213
|
+
15. **Use HTTPS** - Always encrypt traffic
|
|
214
|
+
|