@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,536 +0,0 @@
1
- # Effect Schema
2
-
3
- Effect Schema is a powerful library for defining, validating, and transforming data structures with full TypeScript type inference.
4
-
5
- ## Basic Schemas
6
-
7
- ### Primitive Types
8
-
9
- ```typescript
10
- import { Schema } from "effect"
11
-
12
- // Basic primitives
13
- const str = Schema.String // Schema<string>
14
- const num = Schema.Number // Schema<number>
15
- const bool = Schema.Boolean // Schema<boolean>
16
- const bigint = Schema.BigInt // Schema<bigint>
17
-
18
- // Literals
19
- const literal = Schema.Literal("active", "inactive")
20
- // Schema<"active" | "inactive">
21
-
22
- // Unknown and Any
23
- const unknown = Schema.Unknown // Schema<unknown>
24
- const any = Schema.Any // Schema<any>
25
-
26
- // Void and Undefined
27
- const voidSchema = Schema.Void
28
- const undef = Schema.Undefined
29
- const nil = Schema.Null
30
- ```
31
-
32
- ### Objects (Struct)
33
-
34
- ```typescript
35
- import { Schema } from "effect"
36
-
37
- const User = Schema.Struct({
38
- id: Schema.String,
39
- name: Schema.String,
40
- email: Schema.String,
41
- age: Schema.Number,
42
- isActive: Schema.Boolean
43
- })
44
-
45
- // Infer TypeScript type
46
- type User = Schema.Schema.Type<typeof User>
47
- // { id: string; name: string; email: string; age: number; isActive: boolean }
48
- ```
49
-
50
- ### Optional Fields
51
-
52
- ```typescript
53
- import { Schema } from "effect"
54
-
55
- const User = Schema.Struct({
56
- id: Schema.String,
57
- name: Schema.String,
58
- bio: Schema.optional(Schema.String), // string | undefined
59
- age: Schema.optional(Schema.Number, { exact: true }), // number | undefined (no null)
60
- nickname: Schema.optionalWith(Schema.String, { default: () => "Anonymous" })
61
- })
62
-
63
- // With default value
64
- const Config = Schema.Struct({
65
- host: Schema.String,
66
- port: Schema.optionalWith(Schema.Number, { default: () => 3000 }),
67
- debug: Schema.optionalWith(Schema.Boolean, { default: () => false })
68
- })
69
- ```
70
-
71
- ### Arrays and Tuples
72
-
73
- ```typescript
74
- import { Schema } from "effect"
75
-
76
- // Array
77
- const Numbers = Schema.Array(Schema.Number)
78
- // Schema<number[]>
79
-
80
- // Non-empty array
81
- const NonEmptyNumbers = Schema.NonEmptyArray(Schema.Number)
82
- // Schema<[number, ...number[]]>
83
-
84
- // Tuple
85
- const Point = Schema.Tuple(Schema.Number, Schema.Number)
86
- // Schema<[number, number]>
87
-
88
- // Tuple with rest
89
- const Args = Schema.Tuple(
90
- [Schema.String], // First element
91
- Schema.Number // Rest elements
92
- )
93
- // Schema<[string, ...number[]]>
94
- ```
95
-
96
- ### Unions
97
-
98
- ```typescript
99
- import { Schema } from "effect"
100
-
101
- // Union of schemas
102
- const StringOrNumber = Schema.Union(Schema.String, Schema.Number)
103
- // Schema<string | number>
104
-
105
- // Discriminated union
106
- const Shape = Schema.Union(
107
- Schema.Struct({
108
- type: Schema.Literal("circle"),
109
- radius: Schema.Number
110
- }),
111
- Schema.Struct({
112
- type: Schema.Literal("rectangle"),
113
- width: Schema.Number,
114
- height: Schema.Number
115
- })
116
- )
117
- // Schema<{ type: "circle"; radius: number } | { type: "rectangle"; width: number; height: number }>
118
- ```
119
-
120
- ### Records
121
-
122
- ```typescript
123
- import { Schema } from "effect"
124
-
125
- // Record with string keys
126
- const StringRecord = Schema.Record({
127
- key: Schema.String,
128
- value: Schema.Number
129
- })
130
- // Schema<Record<string, number>>
131
-
132
- // Record with literal keys
133
- const StatusCounts = Schema.Record({
134
- key: Schema.Literal("active", "inactive", "pending"),
135
- value: Schema.Number
136
- })
137
- // Schema<Record<"active" | "inactive" | "pending", number>>
138
- ```
139
-
140
- ## Decoding and Encoding
141
-
142
- ### Synchronous Decoding
143
-
144
- ```typescript
145
- import { Schema } from "effect"
146
-
147
- const User = Schema.Struct({
148
- id: Schema.String,
149
- name: Schema.String,
150
- age: Schema.Number
151
- })
152
-
153
- // Decode unknown data (throws on failure)
154
- const user = Schema.decodeUnknownSync(User)({
155
- id: "123",
156
- name: "Alice",
157
- age: 30
158
- })
159
- // { id: "123", name: "Alice", age: 30 }
160
-
161
- // Throws ParseError on invalid data
162
- try {
163
- Schema.decodeUnknownSync(User)({ id: 123 }) // id should be string
164
- } catch (e) {
165
- console.log(e) // ParseError
166
- }
167
- ```
168
-
169
- ### Effect-based Decoding
170
-
171
- ```typescript
172
- import { Schema, Effect } from "effect"
173
-
174
- const User = Schema.Struct({
175
- id: Schema.String,
176
- name: Schema.String
177
- })
178
-
179
- // Returns Effect<User, ParseError, never>
180
- const decode = Schema.decodeUnknown(User)
181
-
182
- const program = Effect.gen(function* () {
183
- const user = yield* decode({ id: "123", name: "Alice" })
184
- return user
185
- })
186
- ```
187
-
188
- ### Either-based Decoding
189
-
190
- ```typescript
191
- import { Schema, Either } from "effect"
192
-
193
- const User = Schema.Struct({
194
- id: Schema.String,
195
- name: Schema.String
196
- })
197
-
198
- // Returns Either<User, ParseError>
199
- const result = Schema.decodeUnknownEither(User)({
200
- id: "123",
201
- name: "Alice"
202
- })
203
-
204
- if (Either.isRight(result)) {
205
- console.log(result.right) // User
206
- } else {
207
- console.log(result.left) // ParseError
208
- }
209
- ```
210
-
211
- ### Encoding
212
-
213
- ```typescript
214
- import { Schema } from "effect"
215
-
216
- const User = Schema.Struct({
217
- id: Schema.String,
218
- createdAt: Schema.Date // Encodes to ISO string
219
- })
220
-
221
- type User = Schema.Schema.Type<typeof User>
222
- // { id: string; createdAt: Date }
223
-
224
- type UserEncoded = Schema.Schema.Encoded<typeof User>
225
- // { id: string; createdAt: string }
226
-
227
- const user: User = { id: "123", createdAt: new Date() }
228
-
229
- // Encode to serializable form
230
- const encoded = Schema.encodeSync(User)(user)
231
- // { id: "123", createdAt: "2024-01-15T..." }
232
- ```
233
-
234
- ## Transformations
235
-
236
- ### Built-in Transformations
237
-
238
- ```typescript
239
- import { Schema } from "effect"
240
-
241
- // String to Number
242
- const NumberFromString = Schema.NumberFromString
243
- Schema.decodeUnknownSync(NumberFromString)("42") // 42
244
-
245
- // Date from string
246
- const DateFromString = Schema.Date
247
- Schema.decodeUnknownSync(DateFromString)("2024-01-15") // Date object
248
-
249
- // Trim whitespace
250
- const Trimmed = Schema.Trimmed
251
- Schema.decodeUnknownSync(Trimmed)(" hello ") // "hello"
252
-
253
- // Lowercase
254
- const Lowercased = Schema.Lowercased
255
- Schema.decodeUnknownSync(Lowercased)("HELLO") // "hello"
256
- ```
257
-
258
- ### Custom Transformations
259
-
260
- ```typescript
261
- import { Schema } from "effect"
262
-
263
- // Transform between encoded and decoded types
264
- const Cents = Schema.transform(
265
- Schema.Number, // From (encoded)
266
- Schema.Number, // To (decoded)
267
- {
268
- decode: (n) => Math.round(n * 100), // dollars to cents
269
- encode: (n) => n / 100 // cents to dollars
270
- }
271
- )
272
-
273
- const price = Schema.decodeUnknownSync(Cents)(19.99) // 1999
274
- const encoded = Schema.encodeSync(Cents)(1999) // 19.99
275
- ```
276
-
277
- ### Transform with Effects
278
-
279
- ```typescript
280
- import { Schema, Effect } from "effect"
281
-
282
- // Async transformation
283
- const UserFromId = Schema.transformOrFail(
284
- Schema.String,
285
- Schema.Struct({ id: Schema.String, name: Schema.String }),
286
- {
287
- decode: (id) => Effect.tryPromise({
288
- try: () => fetchUser(id),
289
- catch: () => new Error(`User not found: ${id}`)
290
- }),
291
- encode: (user) => Effect.succeed(user.id)
292
- }
293
- )
294
- ```
295
-
296
- ## Refinements and Filters
297
-
298
- ### Built-in Refinements
299
-
300
- ```typescript
301
- import { Schema } from "effect"
302
-
303
- // String refinements
304
- const NonEmpty = Schema.NonEmptyString
305
- const Email = Schema.String.pipe(Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/))
306
- const MinLength = Schema.String.pipe(Schema.minLength(3))
307
- const MaxLength = Schema.String.pipe(Schema.maxLength(100))
308
-
309
- // Number refinements
310
- const Positive = Schema.Number.pipe(Schema.positive())
311
- const NonNegative = Schema.Number.pipe(Schema.nonNegative())
312
- const Int = Schema.Number.pipe(Schema.int())
313
- const Between = Schema.Number.pipe(Schema.between(1, 100))
314
-
315
- // Array refinements
316
- const NonEmptyArray = Schema.Array(Schema.String).pipe(Schema.minItems(1))
317
- const MaxItems = Schema.Array(Schema.Number).pipe(Schema.maxItems(10))
318
- ```
319
-
320
- ### Custom Refinements
321
-
322
- ```typescript
323
- import { Schema } from "effect"
324
-
325
- // Filter with predicate
326
- const EvenNumber = Schema.Number.pipe(
327
- Schema.filter((n) => n % 2 === 0, {
328
- message: () => "Expected even number"
329
- })
330
- )
331
-
332
- // Brand for nominal typing
333
- const UserId = Schema.String.pipe(Schema.brand("UserId"))
334
- type UserId = Schema.Schema.Type<typeof UserId>
335
- // string & Brand<"UserId">
336
-
337
- const OrderId = Schema.String.pipe(Schema.brand("OrderId"))
338
- type OrderId = Schema.Schema.Type<typeof OrderId>
339
-
340
- // Cannot mix: userId = orderId would be type error
341
- ```
342
-
343
- ## Common Patterns
344
-
345
- ### API Request/Response Schemas
346
-
347
- ```typescript
348
- import { Schema } from "effect"
349
-
350
- // Request schema
351
- const CreateUserRequest = Schema.Struct({
352
- name: Schema.NonEmptyString,
353
- email: Schema.String.pipe(
354
- Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)
355
- ),
356
- age: Schema.Number.pipe(Schema.int(), Schema.between(0, 150))
357
- })
358
-
359
- // Response schema (includes generated fields)
360
- const UserResponse = Schema.Struct({
361
- id: Schema.String,
362
- name: Schema.String,
363
- email: Schema.String,
364
- age: Schema.Number,
365
- createdAt: Schema.Date
366
- })
367
-
368
- // List response with pagination
369
- const UsersListResponse = Schema.Struct({
370
- data: Schema.Array(UserResponse),
371
- total: Schema.Number,
372
- page: Schema.Number,
373
- pageSize: Schema.Number
374
- })
375
- ```
376
-
377
- ### Configuration Schema
378
-
379
- ```typescript
380
- import { Schema } from "effect"
381
-
382
- const DatabaseConfig = Schema.Struct({
383
- host: Schema.NonEmptyString,
384
- port: Schema.Number.pipe(Schema.int(), Schema.between(1, 65535)),
385
- database: Schema.NonEmptyString,
386
- username: Schema.NonEmptyString,
387
- password: Schema.NonEmptyString,
388
- ssl: Schema.optionalWith(Schema.Boolean, { default: () => false }),
389
- poolSize: Schema.optionalWith(
390
- Schema.Number.pipe(Schema.int(), Schema.positive()),
391
- { default: () => 10 }
392
- )
393
- })
394
-
395
- const AppConfig = Schema.Struct({
396
- env: Schema.Literal("development", "staging", "production"),
397
- port: Schema.Number.pipe(Schema.int(), Schema.between(1, 65535)),
398
- database: DatabaseConfig,
399
- logLevel: Schema.optionalWith(
400
- Schema.Literal("debug", "info", "warn", "error"),
401
- { default: () => "info" as const }
402
- )
403
- })
404
- ```
405
-
406
- ### Discriminated Union for Events
407
-
408
- ```typescript
409
- import { Schema } from "effect"
410
-
411
- const UserCreated = Schema.Struct({
412
- type: Schema.Literal("UserCreated"),
413
- userId: Schema.String,
414
- email: Schema.String,
415
- timestamp: Schema.Date
416
- })
417
-
418
- const UserUpdated = Schema.Struct({
419
- type: Schema.Literal("UserUpdated"),
420
- userId: Schema.String,
421
- changes: Schema.Record({ key: Schema.String, value: Schema.Unknown }),
422
- timestamp: Schema.Date
423
- })
424
-
425
- const UserDeleted = Schema.Struct({
426
- type: Schema.Literal("UserDeleted"),
427
- userId: Schema.String,
428
- timestamp: Schema.Date
429
- })
430
-
431
- const UserEvent = Schema.Union(UserCreated, UserUpdated, UserDeleted)
432
- type UserEvent = Schema.Schema.Type<typeof UserEvent>
433
-
434
- // Handle events with exhaustive matching
435
- const handleEvent = (event: UserEvent) => {
436
- switch (event.type) {
437
- case "UserCreated":
438
- return `User ${event.userId} created`
439
- case "UserUpdated":
440
- return `User ${event.userId} updated`
441
- case "UserDeleted":
442
- return `User ${event.userId} deleted`
443
- }
444
- }
445
- ```
446
-
447
- ### Extend and Compose Schemas
448
-
449
- ```typescript
450
- import { Schema } from "effect"
451
-
452
- // Base schema
453
- const BaseEntity = Schema.Struct({
454
- id: Schema.String,
455
- createdAt: Schema.Date,
456
- updatedAt: Schema.Date
457
- })
458
-
459
- // Extend with additional fields
460
- const User = Schema.Struct({
461
- ...BaseEntity.fields,
462
- name: Schema.String,
463
- email: Schema.String
464
- })
465
-
466
- // Pick specific fields
467
- const UserSummary = Schema.pick(User, "id", "name")
468
- // Schema<{ id: string; name: string }>
469
-
470
- // Omit specific fields
471
- const UserWithoutDates = Schema.omit(User, "createdAt", "updatedAt")
472
- // Schema<{ id: string; name: string; email: string }>
473
-
474
- // Make all fields optional
475
- const PartialUser = Schema.partial(User)
476
- // Schema<{ id?: string; name?: string; ... }>
477
- ```
478
-
479
- ## Error Handling
480
-
481
- ### Parse Errors
482
-
483
- ```typescript
484
- import { Schema, Either } from "effect"
485
-
486
- const User = Schema.Struct({
487
- id: Schema.String,
488
- age: Schema.Number.pipe(Schema.positive())
489
- })
490
-
491
- const result = Schema.decodeUnknownEither(User)({
492
- id: 123, // Wrong type
493
- age: -5 // Negative
494
- })
495
-
496
- if (Either.isLeft(result)) {
497
- // Access detailed error information
498
- const error = result.left
499
- console.log(error.message)
500
- // Contains path, expected type, actual value
501
- }
502
- ```
503
-
504
- ### Custom Error Messages
505
-
506
- ```typescript
507
- import { Schema } from "effect"
508
-
509
- const Email = Schema.String.pipe(
510
- Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, {
511
- message: () => "Invalid email format"
512
- })
513
- )
514
-
515
- const Age = Schema.Number.pipe(
516
- Schema.between(0, 150, {
517
- message: () => "Age must be between 0 and 150"
518
- })
519
- )
520
-
521
- const Password = Schema.String.pipe(
522
- Schema.minLength(8, { message: () => "Password must be at least 8 characters" }),
523
- Schema.pattern(/[A-Z]/, { message: () => "Password must contain uppercase" }),
524
- Schema.pattern(/[0-9]/, { message: () => "Password must contain a number" })
525
- )
526
- ```
527
-
528
- ## Best Practices
529
-
530
- 1. **Infer types from schemas** - Use `Schema.Schema.Type<typeof X>` instead of manual types
531
- 2. **Use brands for domain types** - Prevents mixing IDs of different entities
532
- 3. **Validate at boundaries** - Decode external data early, work with typed data internally
533
- 4. **Compose schemas** - Build complex schemas from simpler ones
534
- 5. **Add custom error messages** - Make validation errors user-friendly
535
- 6. **Use transformations** - Handle format differences between API and domain
536
- 7. **Keep schemas close to usage** - Define schemas where they're used or in a shared module