@martinffx/atelier 2.0.0 → 3.0.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +94 -253
  3. package/package.json +1 -1
  4. package/skills/{spec-orchestrator → atelier-orchestrator}/SKILL.md +3 -3
  5. package/skills/atelier-setup/SKILL.md +80 -0
  6. package/skills/code-review/references/reviewers.md +3 -3
  7. package/skills/code-review/references/rq.md +6 -6
  8. package/skills/spec-brainstorm/SKILL.md +5 -5
  9. package/skills/spec-implement/SKILL.md +2 -3
  10. package/skills/spec-plan/SKILL.md +21 -29
  11. package/skills/spec-plan/references/plan_template.md +77 -0
  12. package/skills/python-architecture/SKILL.md +0 -148
  13. package/skills/python-architecture/references/data-modeling.md +0 -558
  14. package/skills/python-architecture/references/ddd.md +0 -569
  15. package/skills/python-architecture/references/functional-core.md +0 -337
  16. package/skills/python-build-tools/SKILL.md +0 -153
  17. package/skills/python-build-tools/references/basedpyright.md +0 -321
  18. package/skills/python-build-tools/references/ruff.md +0 -225
  19. package/skills/python-build-tools/references/uv.md +0 -257
  20. package/skills/python-fastapi/SKILL.md +0 -184
  21. package/skills/python-fastapi/references/api-design.md +0 -563
  22. package/skills/python-fastapi/references/dependencies.md +0 -479
  23. package/skills/python-fastapi/references/middleware.md +0 -475
  24. package/skills/python-fastapi/references/validation.md +0 -497
  25. package/skills/python-modern-python/SKILL.md +0 -201
  26. package/skills/python-modern-python/references/async.md +0 -76
  27. package/skills/python-modern-python/references/pattern-matching.md +0 -89
  28. package/skills/python-modern-python/references/typing.md +0 -96
  29. package/skills/python-monorepo/SKILL.md +0 -146
  30. package/skills/python-monorepo/references/docker.md +0 -515
  31. package/skills/python-monorepo/references/namespace-packages.md +0 -426
  32. package/skills/python-monorepo/references/workspace-config.md +0 -341
  33. package/skills/python-sqlalchemy/SKILL.md +0 -119
  34. package/skills/python-sqlalchemy/references/async.md +0 -51
  35. package/skills/python-sqlalchemy/references/models.md +0 -67
  36. package/skills/python-sqlalchemy/references/queries.md +0 -57
  37. package/skills/python-temporal/SKILL.md +0 -128
  38. package/skills/python-temporal/references/patterns.md +0 -87
  39. package/skills/python-temporal/references/testing.md +0 -54
  40. package/skills/python-testing/SKILL.md +0 -161
  41. package/skills/python-testing/references/boundaries.md +0 -449
  42. package/skills/python-testing/references/mocking.md +0 -449
  43. package/skills/python-testing/references/pytest.md +0 -524
  44. package/skills/typescript-api-design/SKILL.md +0 -396
  45. package/skills/typescript-api-design/references/error-responses.md +0 -469
  46. package/skills/typescript-build-tools/SKILL.md +0 -447
  47. package/skills/typescript-build-tools/references/biome.md +0 -436
  48. package/skills/typescript-build-tools/references/bun.md +0 -432
  49. package/skills/typescript-build-tools/references/turborepo.md +0 -426
  50. package/skills/typescript-build-tools/references/vitest.md +0 -518
  51. package/skills/typescript-drizzle-orm/SKILL.md +0 -398
  52. package/skills/typescript-drizzle-orm/references/cloudflare.md +0 -392
  53. package/skills/typescript-drizzle-orm/references/entity-pattern.md +0 -412
  54. package/skills/typescript-drizzle-orm/references/postgresql.md +0 -191
  55. package/skills/typescript-drizzle-orm/references/repository-pattern.md +0 -479
  56. package/skills/typescript-drizzle-orm/references/sqlite.md +0 -291
  57. package/skills/typescript-dynamodb-toolbox/SKILL.md +0 -370
  58. package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +0 -574
  59. package/skills/typescript-dynamodb-toolbox/references/error-handling.md +0 -495
  60. package/skills/typescript-dynamodb-toolbox/references/modeling.md +0 -332
  61. package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +0 -631
  62. package/skills/typescript-dynamodb-toolbox/references/testing.md +0 -718
  63. package/skills/typescript-dynamodb-toolbox/references/transactions.md +0 -423
  64. package/skills/typescript-effect-ts/SKILL.md +0 -341
  65. package/skills/typescript-effect-ts/references/core.md +0 -412
  66. package/skills/typescript-effect-ts/references/error-handling.md +0 -468
  67. package/skills/typescript-effect-ts/references/resources.md +0 -476
  68. package/skills/typescript-effect-ts/references/schema.md +0 -536
  69. package/skills/typescript-effect-ts/references/services.md +0 -461
  70. package/skills/typescript-fastify/SKILL.md +0 -405
  71. package/skills/typescript-fastify/references/plugins.md +0 -329
  72. package/skills/typescript-fastify/references/typeid.md +0 -315
  73. package/skills/typescript-functional-patterns/SKILL.md +0 -402
  74. package/skills/typescript-functional-patterns/references/adts.md +0 -497
  75. package/skills/typescript-functional-patterns/references/branded-types.md +0 -542
  76. package/skills/typescript-functional-patterns/references/migration-guide.md +0 -695
  77. package/skills/typescript-functional-patterns/references/option-result.md +0 -585
  78. package/skills/typescript-testing/SKILL.md +0 -353
  79. package/skills/typescript-testing/references/mocking.md +0 -675
  80. package/skills/typescript-testing/references/msw.md +0 -852
  81. package/skills/typescript-testing/references/snapshot-testing.md +0 -774
@@ -1,405 +0,0 @@
1
- ---
2
- name: typescript-fastify
3
- description: Building REST APIs with Fastify in TypeScript. Use when creating routes, handling requests, implementing validation with TypeBox, structuring applications, or working with HTTP handlers and plugins.
4
- user-invocable: false
5
- ---
6
-
7
- # Fastify
8
-
9
- Fast, low-overhead web framework for Node.js with TypeBox schema validation.
10
-
11
- ## Additional References
12
-
13
- - [references/plugins.md](./references/plugins.md) - Plugin architecture and dependency injection
14
- - [references/typeid.md](./references/typeid.md) - Type-safe prefixed identifiers
15
-
16
- ## Setup
17
-
18
- ```bash
19
- npm i fastify @fastify/type-provider-typebox @sinclair/typebox
20
- ```
21
-
22
- ```typescript
23
- import Fastify from 'fastify'
24
- import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
25
-
26
- const app = Fastify({ logger: true }).withTypeProvider<TypeBoxTypeProvider>()
27
- ```
28
-
29
- ## Schema Definition
30
-
31
- ```typescript
32
- import { Type, Static } from '@sinclair/typebox'
33
-
34
- // Request/response schemas with $id for OpenAPI
35
- export const UserSchema = Type.Object({
36
- id: Type.String({ format: 'uuid' }),
37
- name: Type.String({ minLength: 1, maxLength: 100 }),
38
- email: Type.String({ format: 'email' }),
39
- createdAt: Type.String({ format: 'date-time' }),
40
- }, { $id: 'UserResponse' })
41
-
42
- export type User = Static<typeof UserSchema>
43
-
44
- // Input schemas (omit generated fields)
45
- export const CreateUserSchema = Type.Object({
46
- name: Type.String({ minLength: 1, maxLength: 100 }),
47
- email: Type.String({ format: 'email' }),
48
- }, { $id: 'CreateUserRequest' })
49
-
50
- export type CreateUserInput = Static<typeof CreateUserSchema>
51
- ```
52
-
53
- ## Route with Full Schema
54
-
55
- ```typescript
56
- const TAGS = ['Users']
57
-
58
- app.post('/users', {
59
- schema: {
60
- operationId: 'createUser',
61
- tags: TAGS,
62
- summary: 'Create a new user',
63
- description: 'Create a new user account',
64
- body: CreateUserSchema,
65
- response: {
66
- 201: UserSchema,
67
- 400: BadRequestErrorResponse,
68
- 401: UnauthorizedErrorResponse,
69
- 500: InternalServerErrorResponse,
70
- },
71
- },
72
- }, async (request, reply) => {
73
- const { name, email } = request.body // fully typed
74
-
75
- const user = await createUser({ name, email })
76
- return reply.status(201).send(user)
77
- })
78
- ```
79
-
80
- ## Common Schema Patterns
81
-
82
- ```typescript
83
- // Path parameters
84
- const ParamsSchema = Type.Object({
85
- id: Type.String({ format: 'uuid' }),
86
- })
87
-
88
- // Query string with pagination
89
- const QuerySchema = Type.Object({
90
- limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100, default: 20 })),
91
- cursor: Type.Optional(Type.String()),
92
- sort: Type.Optional(Type.Union([Type.Literal('asc'), Type.Literal('desc')])),
93
- })
94
-
95
- // Paginated response wrapper
96
- const PaginatedResponse = <T extends TSchema>(itemSchema: T) =>
97
- Type.Object({
98
- items: Type.Array(itemSchema),
99
- nextCursor: Type.Optional(Type.String()),
100
- hasMore: Type.Boolean(),
101
- })
102
-
103
- app.get('/users/:id', {
104
- schema: {
105
- operationId: 'getUser',
106
- tags: ['Users'],
107
- summary: 'Get user by ID',
108
- params: ParamsSchema,
109
- querystring: QuerySchema,
110
- response: {
111
- 200: UserSchema,
112
- 400: BadRequestErrorResponse,
113
- 404: NotFoundErrorResponse,
114
- 500: InternalServerErrorResponse,
115
- },
116
- },
117
- }, async (request, reply) => {
118
- const { id } = request.params
119
- const { limit, cursor } = request.query
120
- // ...
121
- })
122
- ```
123
-
124
- ## Modular Route Registration
125
-
126
- ```typescript
127
- // types.ts - Export typed Fastify instance
128
- import {
129
- FastifyInstance,
130
- FastifyBaseLogger,
131
- RawReplyDefaultExpression,
132
- RawRequestDefaultExpression,
133
- RawServerDefault,
134
- } from 'fastify'
135
- import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
136
-
137
- export type FastifyTypebox = FastifyInstance<
138
- RawServerDefault,
139
- RawRequestDefaultExpression<RawServerDefault>,
140
- RawReplyDefaultExpression<RawServerDefault>,
141
- FastifyBaseLogger,
142
- TypeBoxTypeProvider
143
- >
144
- ```
145
-
146
- ```typescript
147
- // routes/users.ts
148
- import { Type } from '@sinclair/typebox'
149
- import { FastifyTypebox } from '../types'
150
-
151
- export async function userRoutes(app: FastifyTypebox) {
152
- app.get('/users', {
153
- schema: {
154
- response: {
155
- 200: Type.Array(UserSchema),
156
- },
157
- },
158
- }, async () => {
159
- return await listUsers()
160
- })
161
- }
162
- ```
163
-
164
- ```typescript
165
- // index.ts
166
- import { userRoutes } from './routes/users'
167
-
168
- app.register(userRoutes, { prefix: '/api/v1' })
169
- ```
170
-
171
- ## Error Schemas (RFC 7807)
172
-
173
- Use standardized error responses across all routes:
174
-
175
- ```typescript
176
- import { Type } from '@sinclair/typebox'
177
-
178
- // Base ProblemDetail schema (RFC 7807)
179
- const ProblemDetail = Type.Object({
180
- type: Type.String(),
181
- status: Type.Number(),
182
- title: Type.String(),
183
- detail: Type.String(),
184
- instance: Type.String(),
185
- traceId: Type.String(),
186
- })
187
-
188
- // Specific error responses
189
- export const BadRequestErrorResponse = Type.Composite([
190
- ProblemDetail,
191
- Type.Object({
192
- type: Type.Literal('BAD_REQUEST'),
193
- status: Type.Literal(400),
194
- }),
195
- ], { $id: 'BadRequestErrorResponse' })
196
-
197
- export const UnauthorizedErrorResponse = Type.Composite([
198
- ProblemDetail,
199
- Type.Object({
200
- type: Type.Literal('UNAUTHORIZED'),
201
- status: Type.Literal(401),
202
- }),
203
- ], { $id: 'UnauthorizedErrorResponse' })
204
-
205
- export const ForbiddenErrorResponse = Type.Composite([
206
- ProblemDetail,
207
- Type.Object({
208
- type: Type.Literal('FORBIDDEN'),
209
- status: Type.Literal(403),
210
- }),
211
- ], { $id: 'ForbiddenErrorResponse' })
212
-
213
- export const NotFoundErrorResponse = Type.Composite([
214
- ProblemDetail,
215
- Type.Object({
216
- type: Type.Literal('NOT_FOUND'),
217
- status: Type.Literal(404),
218
- }),
219
- ], { $id: 'NotFoundErrorResponse' })
220
-
221
- export const InternalServerErrorResponse = Type.Composite([
222
- ProblemDetail,
223
- Type.Object({
224
- type: Type.Literal('INTERNAL_SERVER_ERROR'),
225
- status: Type.Literal(500),
226
- }),
227
- ], { $id: 'InternalServerErrorResponse' })
228
- ```
229
-
230
- ## Error Handling
231
-
232
- ```typescript
233
- import { FastifyError, FastifyRequest, FastifyReply } from 'fastify'
234
-
235
- // Custom error handler
236
- const globalErrorHandler = (
237
- error: FastifyError,
238
- request: FastifyRequest,
239
- reply: FastifyReply
240
- ) => {
241
- // Handle Fastify validation errors
242
- if (error.code === 'FST_ERR_VALIDATION') {
243
- return reply.status(400).send({
244
- type: 'BAD_REQUEST',
245
- status: 400,
246
- title: 'Validation Error',
247
- detail: error.message,
248
- instance: request.url,
249
- traceId: request.id,
250
- })
251
- }
252
-
253
- // Handle domain errors (if using error classes)
254
- if (error instanceof AppError) {
255
- return reply.status(error.status).send(error.toResponse())
256
- }
257
-
258
- // Default to internal server error
259
- request.log.error(error)
260
- return reply.status(500).send({
261
- type: 'INTERNAL_SERVER_ERROR',
262
- status: 500,
263
- title: 'Internal Server Error',
264
- detail: 'Something went wrong',
265
- instance: request.url,
266
- traceId: request.id,
267
- })
268
- }
269
-
270
- app.setErrorHandler(globalErrorHandler)
271
- ```
272
-
273
- ## Reusable Schemas (Shared References)
274
-
275
- ```typescript
276
- // Add schema to instance for $ref usage
277
- app.addSchema({
278
- $id: 'User',
279
- ...UserSchema,
280
- })
281
-
282
- app.addSchema({
283
- $id: 'Error',
284
- ...ErrorSchema,
285
- })
286
-
287
- // Reference in routes
288
- app.get('/me', {
289
- schema: {
290
- response: {
291
- 200: Type.Ref('User'),
292
- 401: Type.Ref('Error'),
293
- },
294
- },
295
- }, handler)
296
- ```
297
-
298
- ## Headers and Auth
299
-
300
- ```typescript
301
- const AuthHeadersSchema = Type.Object({
302
- authorization: Type.String({ pattern: '^Bearer .+$' }),
303
- })
304
-
305
- app.get('/protected', {
306
- schema: {
307
- headers: AuthHeadersSchema,
308
- response: {
309
- 200: UserSchema,
310
- 401: UnauthorizedErrorResponse,
311
- },
312
- },
313
- preValidation: async (request, reply) => {
314
- const token = request.headers.authorization?.replace('Bearer ', '')
315
- if (!token || !verifyToken(token)) {
316
- throw new UnauthorizedError('Invalid or missing token')
317
- }
318
- },
319
- }, handler)
320
- ```
321
-
322
- ## Auth & Permissions
323
-
324
- Role-based permission checks with decorators:
325
-
326
- ```typescript
327
- import type { FastifyRequest, FastifyReply } from 'fastify'
328
-
329
- // Permission constants
330
- const Permissions = [
331
- 'user:read',
332
- 'user:write',
333
- 'user:delete',
334
- 'admin:access',
335
- ] as const
336
-
337
- type Permission = typeof Permissions[number]
338
-
339
- // Role-based permission sets
340
- const RolePermissions = {
341
- admin: new Set<Permission>(['user:read', 'user:write', 'user:delete', 'admin:access']),
342
- user: new Set<Permission>(['user:read', 'user:write']),
343
- readonly: new Set<Permission>(['user:read']),
344
- } as const
345
-
346
- // Extend FastifyRequest with token data
347
- declare module 'fastify' {
348
- interface FastifyRequest {
349
- token: {
350
- userId: string
351
- role: keyof typeof RolePermissions
352
- permissions: Permission[]
353
- }
354
- }
355
- }
356
-
357
- // Permission check decorator
358
- app.decorate('hasPermissions', (requiredPermissions: Permission[]) => {
359
- return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
360
- const userPermissions = request.token.permissions
361
-
362
- for (const permission of requiredPermissions) {
363
- if (!userPermissions.includes(permission)) {
364
- throw new ForbiddenError(`Missing permission: ${permission}`)
365
- }
366
- }
367
- }
368
- })
369
-
370
- // Usage in routes
371
- app.delete('/users/:id', {
372
- schema: {
373
- operationId: 'deleteUser',
374
- tags: ['Users'],
375
- params: Type.Object({ id: Type.String() }),
376
- response: {
377
- 204: Type.Null(),
378
- 401: UnauthorizedErrorResponse,
379
- 403: ForbiddenErrorResponse,
380
- 404: NotFoundErrorResponse,
381
- },
382
- },
383
- preHandler: app.hasPermissions(['user:delete']),
384
- }, async (request, reply) => {
385
- await deleteUser(request.params.id)
386
- return reply.status(204).send()
387
- })
388
- ```
389
-
390
- ## Guidelines
391
-
392
- 1. Always define schemas with `Type.Object({ ... })` - full JSON Schema required in Fastify v5
393
- 2. Add `$id` to all schemas for OpenAPI generation and reusability
394
- 3. Add `operationId`, `tags`, and `summary` to all routes for documentation
395
- 4. Define response schemas for ALL status codes (200, 400, 401, 403, 404, 500)
396
- 5. Use RFC 7807 ProblemDetail format for errors with `Type.Composite`
397
- 6. Use `Static<typeof Schema>` to derive TypeScript types from schemas
398
- 7. Split input schemas (CreateX) from output schemas (X) - omit generated fields
399
- 8. Use `Type.Optional()` for optional fields, not `?` in the type
400
- 9. Export `FastifyTypebox` type for modular route files
401
- 10. Add format validators: `uuid`, `email`, `date-time`, `uri`
402
- 11. Use `Type.Union([Type.Literal(...)])` for string enums
403
- 12. Use Fastify plugins with `fp()` for dependency injection - see [references/plugins.md](./references/plugins.md)
404
- 13. Use `preHandler` with `hasPermissions()` decorator for protected routes
405
- 14. Use TypeID for type-safe prefixed identifiers - see [references/typeid.md](./references/typeid.md)