@martinffx/atelier 2.0.0 → 3.0.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +21 -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,398 +0,0 @@
1
- ---
2
- name: typescript-drizzle-orm
3
- description: Type-safe SQL with Drizzle ORM in TypeScript. Use when defining database schemas, writing queries, setting up relations, running migrations, or working with PostgreSQL/MySQL/SQLite/Cloudflare D1/Durable Objects data layers.
4
- user-invocable: false
5
- ---
6
-
7
- # Drizzle ORM
8
-
9
- Lightweight, type-safe ORM with SQL-like and relational query APIs for PostgreSQL, MySQL, SQLite, Cloudflare D1, and Durable Objects.
10
-
11
- ## Quick Start (PostgreSQL)
12
-
13
- ```typescript
14
- import {
15
- pgTable,
16
- serial,
17
- text,
18
- integer,
19
- timestamp,
20
- boolean,
21
- varchar,
22
- uuid,
23
- primaryKey,
24
- unique,
25
- index
26
- } from 'drizzle-orm/pg-core'
27
-
28
- export const users = pgTable('users', {
29
- id: serial('id').primaryKey(),
30
- name: text('name').notNull(),
31
- email: varchar('email', { length: 255 }).notNull().unique(),
32
- age: integer('age'),
33
- isActive: boolean('is_active').default(true),
34
- createdAt: timestamp('created_at').defaultNow().notNull(),
35
- updatedAt: timestamp('updated_at').$onUpdate(() => new Date()),
36
- })
37
-
38
- export const posts = pgTable('posts', {
39
- id: serial('id').primaryKey(),
40
- title: text('title').notNull(),
41
- content: text('content'),
42
- authorId: integer('author_id')
43
- .notNull()
44
- .references(() => users.id, { onDelete: 'cascade' }),
45
- createdAt: timestamp('created_at').defaultNow().notNull(),
46
- })
47
- ```
48
-
49
- See [references/postgresql.md](./references/postgresql.md) for detailed PostgreSQL patterns.
50
-
51
- ## Quick Start (SQLite/D1)
52
-
53
- ```typescript
54
- import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
55
-
56
- export const users = sqliteTable('users', {
57
- id: text('id').primaryKey(),
58
- name: text('name').notNull(),
59
- email: text('email').notNull(),
60
- isActive: integer('is_active', { mode: 'boolean' }).default(true),
61
- createdAt: text('created_at').notNull(),
62
- })
63
-
64
- export const posts = sqliteTable('posts', {
65
- id: text('id').primaryKey(),
66
- title: text('title').notNull(),
67
- content: text('content'),
68
- authorId: text('author_id')
69
- .notNull()
70
- .references(() => users.id, { onDelete: 'cascade' }),
71
- createdAt: text('created_at').notNull(),
72
- })
73
- ```
74
-
75
- See [references/sqlite.md](./references/sqlite.md) for SQLite patterns and [references/cloudflare.md](./references/cloudflare.md) for D1 and Durable Objects.
76
-
77
- ## Type Inference
78
-
79
- ```typescript
80
- // Infer types from schema - no manual interfaces needed
81
- export type User = typeof users.$inferSelect
82
- export type NewUser = typeof users.$inferInsert
83
-
84
- export type Post = typeof posts.$inferSelect
85
- export type NewPost = typeof posts.$inferInsert
86
- ```
87
-
88
- ## Relations
89
-
90
- ```typescript
91
- import { relations } from 'drizzle-orm'
92
-
93
- export const usersRelations = relations(users, ({ many }) => ({
94
- posts: many(posts),
95
- }))
96
-
97
- export const postsRelations = relations(posts, ({ one }) => ({
98
- author: one(users, {
99
- fields: [posts.authorId],
100
- references: [users.id],
101
- }),
102
- }))
103
- ```
104
-
105
- ## SQL-like Queries
106
-
107
- ```typescript
108
- import { eq, and, or, gt, like, isNull, desc, asc } from 'drizzle-orm'
109
-
110
- // Select all
111
- const allUsers = await db.select().from(users)
112
-
113
- // Select specific columns
114
- const names = await db.select({ name: users.name }).from(users)
115
-
116
- // Where clause
117
- const activeUsers = await db
118
- .select()
119
- .from(users)
120
- .where(eq(users.isActive, true))
121
-
122
- // Multiple conditions
123
- const filtered = await db
124
- .select()
125
- .from(users)
126
- .where(and(
127
- eq(users.isActive, true),
128
- gt(users.age, 18)
129
- ))
130
-
131
- // Like/pattern matching
132
- const matching = await db
133
- .select()
134
- .from(users)
135
- .where(like(users.email, '%@example.com'))
136
-
137
- // Order and limit
138
- const recent = await db
139
- .select()
140
- .from(posts)
141
- .orderBy(desc(posts.createdAt))
142
- .limit(10)
143
-
144
- // Joins
145
- const postsWithAuthors = await db
146
- .select({
147
- postTitle: posts.title,
148
- authorName: users.name,
149
- })
150
- .from(posts)
151
- .leftJoin(users, eq(posts.authorId, users.id))
152
- ```
153
-
154
- ## Relational Queries
155
-
156
- ```typescript
157
- // Requires schema with relations passed to drizzle()
158
- const db = drizzle(pool, { schema })
159
-
160
- // Find many with relations
161
- const usersWithPosts = await db.query.users.findMany({
162
- with: {
163
- posts: true,
164
- },
165
- })
166
-
167
- // Partial columns + nested relations
168
- const partial = await db.query.users.findMany({
169
- columns: {
170
- id: true,
171
- name: true,
172
- },
173
- with: {
174
- posts: {
175
- columns: {
176
- title: true,
177
- createdAt: true,
178
- },
179
- },
180
- },
181
- })
182
-
183
- // Find first
184
- const user = await db.query.users.findFirst({
185
- where: eq(users.id, 1),
186
- with: { posts: true },
187
- })
188
-
189
- // Exclude columns
190
- const withoutEmail = await db.query.users.findMany({
191
- columns: {
192
- email: false, // exclude
193
- },
194
- })
195
- ```
196
-
197
- ## Insert
198
-
199
- ```typescript
200
- // Single insert
201
- const [newUser] = await db
202
- .insert(users)
203
- .values({ name: 'Alice', email: 'alice@example.com' })
204
- .returning()
205
-
206
- // Multiple insert
207
- await db.insert(users).values([
208
- { name: 'Bob', email: 'bob@example.com' },
209
- { name: 'Carol', email: 'carol@example.com' },
210
- ])
211
-
212
- // Upsert (on conflict)
213
- await db
214
- .insert(users)
215
- .values({ name: 'Alice', email: 'alice@example.com' })
216
- .onConflictDoUpdate({
217
- target: users.email,
218
- set: { name: 'Alice Updated' },
219
- })
220
- ```
221
-
222
- ## Update
223
-
224
- ```typescript
225
- await db
226
- .update(users)
227
- .set({ isActive: false })
228
- .where(eq(users.id, 1))
229
-
230
- // Update with returning
231
- const [updated] = await db
232
- .update(users)
233
- .set({ name: 'New Name' })
234
- .where(eq(users.id, 1))
235
- .returning()
236
- ```
237
-
238
- ## Delete
239
-
240
- ```typescript
241
- await db.delete(users).where(eq(users.id, 1))
242
-
243
- // Delete with returning
244
- const [deleted] = await db
245
- .delete(users)
246
- .where(eq(users.id, 1))
247
- .returning()
248
- ```
249
-
250
- ## Transactions
251
-
252
- ```typescript
253
- await db.transaction(async (tx) => {
254
- const [user] = await tx
255
- .insert(users)
256
- .values({ name: 'Alice', email: 'alice@example.com' })
257
- .returning()
258
-
259
- await tx.insert(posts).values({
260
- title: 'First Post',
261
- authorId: user.id,
262
- })
263
- })
264
- ```
265
-
266
- ## Entity Pattern
267
-
268
- Domain entities encapsulate data transformations between API, domain, and database layers.
269
-
270
- ```typescript
271
- import type { InferInsertModel, InferSelectModel } from 'drizzle-orm'
272
- import type { users } from './schema'
273
-
274
- type UserRecord = InferSelectModel<typeof users>
275
- type UserInsert = InferInsertModel<typeof users>
276
-
277
- class UserEntity {
278
- public readonly id: string
279
- public readonly name: string
280
- public readonly email: string
281
- public readonly createdAt: Date
282
-
283
- private constructor(data: UserEntityData) {
284
- Object.assign(this, data)
285
- }
286
-
287
- // API request → Entity
288
- static fromRequest(rq: CreateUserRequest, id?: string): UserEntity {
289
- return new UserEntity({
290
- id: id ?? crypto.randomUUID(),
291
- name: rq.name,
292
- email: rq.email,
293
- createdAt: new Date(),
294
- })
295
- }
296
-
297
- // DB record → Entity
298
- static fromRecord(record: UserRecord): UserEntity {
299
- return new UserEntity({
300
- id: record.id,
301
- name: record.name,
302
- email: record.email,
303
- createdAt: record.createdAt,
304
- })
305
- }
306
-
307
- // Entity → DB insert
308
- toRecord(): UserInsert {
309
- return {
310
- id: this.id,
311
- name: this.name,
312
- email: this.email,
313
- createdAt: this.createdAt,
314
- }
315
- }
316
-
317
- // Entity → API response
318
- toResponse(): UserResponse {
319
- return {
320
- id: this.id,
321
- name: this.name,
322
- email: this.email,
323
- createdAt: this.createdAt.toISOString(),
324
- }
325
- }
326
- }
327
- ```
328
-
329
- See [references/entity-pattern.md](./references/entity-pattern.md) for detailed examples.
330
-
331
- ## Repository Pattern
332
-
333
- Repositories wrap database access with error handling and business logic.
334
-
335
- ```typescript
336
- import { eq, and } from 'drizzle-orm'
337
- import { users } from './schema'
338
- import { UserEntity } from './entities/UserEntity'
339
-
340
- class UserRepo {
341
- constructor(private db: DrizzleDB) {}
342
-
343
- async getById(id: string): Promise<UserEntity> {
344
- const record = await this.db.query.users.findFirst({
345
- where: eq(users.id, id),
346
- })
347
- if (!record) throw new NotFoundError('User not found')
348
- return UserEntity.fromRecord(record)
349
- }
350
-
351
- async create(entity: UserEntity): Promise<UserEntity> {
352
- try {
353
- const [record] = await this.db
354
- .insert(users)
355
- .values(entity.toRecord())
356
- .returning()
357
- return UserEntity.fromRecord(record)
358
- } catch (error) {
359
- throw handleDBError(error, { userId: entity.id })
360
- }
361
- }
362
-
363
- async update(entity: UserEntity): Promise<UserEntity> {
364
- const [record] = await this.db
365
- .update(users)
366
- .set(entity.toRecord())
367
- .where(eq(users.id, entity.id))
368
- .returning()
369
- if (!record) throw new NotFoundError('User not found')
370
- return UserEntity.fromRecord(record)
371
- }
372
- }
373
- ```
374
-
375
- See [references/repository-pattern.md](./references/repository-pattern.md) for detailed examples.
376
-
377
- ## Database-Specific Guides
378
-
379
- For database-specific patterns, connection setup, migrations, and testing:
380
-
381
- - **[PostgreSQL patterns](./references/postgresql.md)** - Connection, migrations, column types, error codes, optimistic locking
382
- - **[SQLite patterns](./references/sqlite.md)** - Schema definition, type differences, better-sqlite3 testing
383
- - **[Cloudflare D1 & Durable Objects](./references/cloudflare.md)** - D1 connection, DO SQLite, testing with vitest-pool-workers, D1 vs DO decision guide
384
-
385
- ## Guidelines
386
-
387
- 1. Define schema in dedicated `schema.ts` file(s)
388
- 2. Use `$inferSelect` and `$inferInsert` for types - don't duplicate
389
- 3. Always define relations for nested queries with `db.query`
390
- 4. Pass `{ schema }` to `drizzle()` to enable relational queries
391
- 5. Use SQL-like API (`db.select()`) for complex joins
392
- 6. Use relational API (`db.query`) for nested data fetching
393
- 7. Foreign keys need explicit `references(() => table.column)`
394
- 8. Use `returning()` to get inserted/updated/deleted rows
395
- 9. Wrap database access in Repository classes for error handling
396
- 10. Use Entity classes for all data transformations (fromRequest, fromRecord, toRecord, toResponse)
397
- 11. Add `lockVersion` column for optimistic locking on mutable resources
398
- 12. Handle DB errors with specific error types (23505=conflict, 23503=not found, 40001/OC000=retry)