@danieljvdm/dev-kit 0.6.0 → 0.7.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 (49) hide show
  1. package/README.md +123 -56
  2. package/dev-kit.example.jsonc +7 -3
  3. package/package.json +19 -16
  4. package/schema/dev-kit.schema.json +38 -0
  5. package/skill-sources.jsonc +8 -12
  6. package/skill-sources.lock.json +3 -9
  7. package/skills/dev-kit/SKILL.md +52 -17
  8. package/skills/effect-ts/agents/openai.yaml +0 -1
  9. package/skills/effect-ts/references/audit-services.md +11 -11
  10. package/skills/effect-ts/references/guide-effect.md +56 -69
  11. package/skills/effect-ts/references/guide-error-handling.md +64 -73
  12. package/skills/effect-ts/references/guide-layers.md +187 -215
  13. package/skills/effect-ts/references/guide-observability.md +91 -116
  14. package/skills/effect-ts/references/guide-retries.md +32 -44
  15. package/skills/effect-ts/references/guide-schedule.md +26 -40
  16. package/skills/effect-ts/references/guide-schema.md +50 -57
  17. package/skills/effect-ts/references/guide-sql.md +47 -50
  18. package/skills/effect-ts/references/guide-testing.md +96 -98
  19. package/skills/effect-ts/references/guide-type-safety-and-boundaries.md +7 -7
  20. package/skills/effect-ts/references/version-and-source.md +0 -1
  21. package/src/bin/dev-kit.ts +61 -28
  22. package/src/catalog-manager.ts +86 -34
  23. package/src/catalog.ts +71 -33
  24. package/src/cli-ui.ts +20 -16
  25. package/src/effect-source.ts +49 -19
  26. package/src/effect-tsgo.ts +66 -35
  27. package/src/gitignore.ts +19 -6
  28. package/src/index.ts +6 -0
  29. package/src/manifest.ts +38 -3
  30. package/src/node-symbolic-link.ts +3 -0
  31. package/src/oxlint-plugin-effect.js +3 -0
  32. package/src/oxlint-plugin-style.d.ts +8 -0
  33. package/src/oxlint-plugin-style.js +8 -0
  34. package/src/oxlint.js +14 -0
  35. package/src/oxlint.ts +14 -0
  36. package/src/package-skill-source.ts +189 -52
  37. package/src/path-digest.ts +47 -13
  38. package/src/project-package.ts +44 -19
  39. package/src/project-process-lock.ts +19 -12
  40. package/src/project-state.ts +11 -0
  41. package/src/skill-manager.ts +134 -55
  42. package/src/skill-selector.ts +8 -2
  43. package/src/source-manifest.ts +2 -6
  44. package/src/sync.ts +417 -107
  45. package/src/vendor.ts +112 -42
  46. package/src/vite-plus-hooks.ts +174 -0
  47. package/src/vite-plus-quality.ts +49 -0
  48. package/templates/vite-plus/github-actions-check.yml +44 -0
  49. package/templates/vite-plus/vite.config.ts +22 -0
@@ -83,18 +83,18 @@ There are two good definition styles:
83
83
  Example:
84
84
 
85
85
  ```ts
86
- import { Context, Effect, Schema } from "effect"
86
+ import { Context, Effect, Schema } from "effect";
87
87
 
88
- class UserRepoError extends Schema.TaggedErrorClass<UserRepoError>()(
89
- "UserRepoError",
88
+ class UserRepoError extends Schema.TaggedErrorClass<UserRepoError>()("UserRepoError", {
89
+ message: Schema.String,
90
+ }) {}
91
+
92
+ class UserRepo extends Context.Service<
93
+ UserRepo,
90
94
  {
91
- message: Schema.String
95
+ readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }, UserRepoError>;
92
96
  }
93
- ) {}
94
-
95
- class UserRepo extends Context.Service<UserRepo, {
96
- readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }, UserRepoError>
97
- }>()("UserRepo") {}
97
+ >()("UserRepo") {}
98
98
  ```
99
99
 
100
100
  Why this style is preferred:
@@ -123,23 +123,18 @@ Repo reference:
123
123
  When the implementation shape is clearer than the interface declaration, prefer using the `make` argument so the service shape is inferred from the implementation.
124
124
 
125
125
  ```ts
126
- import { Context, Effect, Schema } from "effect"
126
+ import { Context, Effect, Schema } from "effect";
127
127
 
128
- class UserRepoError extends Schema.TaggedErrorClass<UserRepoError>()(
129
- "UserRepoError",
130
- {
131
- message: Schema.String
132
- }
133
- ) {}
128
+ class UserRepoError extends Schema.TaggedErrorClass<UserRepoError>()("UserRepoError", {
129
+ message: Schema.String,
130
+ }) {}
134
131
 
135
132
  class UserRepo extends Context.Service<UserRepo>()("UserRepo", {
136
133
  make: Effect.succeed({
137
- getById: Effect.fn("UserRepo.getById")(function*(id: string) {
138
- return yield* Effect.fail(
139
- UserRepoError.make({ message: `User ${id} not found` })
140
- )
141
- })
142
- })
134
+ getById: Effect.fn("UserRepo.getById")(function* (id: string) {
135
+ return yield* Effect.fail(UserRepoError.make({ message: `User ${id} not found` }));
136
+ }),
137
+ }),
143
138
  }) {}
144
139
  ```
145
140
 
@@ -162,24 +157,24 @@ Prefer the explicit generic shape when:
162
157
  ## Service Example
163
158
 
164
159
  ```ts
165
- import { Context, Effect, Schema } from "effect"
160
+ import { Context, Effect, Schema } from "effect";
161
+
162
+ class UserNotFound extends Schema.TaggedErrorClass<UserNotFound>()("UserNotFound", {
163
+ userId: Schema.String,
164
+ }) {}
166
165
 
167
- class UserNotFound extends Schema.TaggedErrorClass<UserNotFound>()(
168
- "UserNotFound",
166
+ class UserRepo extends Context.Service<
167
+ UserRepo,
169
168
  {
170
- userId: Schema.String
169
+ readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }, UserNotFound>;
171
170
  }
172
- ) {}
173
-
174
- class UserRepo extends Context.Service<UserRepo, {
175
- readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }, UserNotFound>
176
- }>()("UserRepo") {}
171
+ >()("UserRepo") {}
177
172
 
178
173
  const loadUser = (userId: string) =>
179
- Effect.gen(function*() {
180
- const repo = yield* UserRepo
181
- return yield* repo.getById(userId)
182
- })
174
+ Effect.gen(function* () {
175
+ const repo = yield* UserRepo;
176
+ return yield* repo.getById(userId);
177
+ });
183
178
  ```
184
179
 
185
180
  Key points:
@@ -213,18 +208,16 @@ Use a full service instead when:
213
208
  Common patterns:
214
209
 
215
210
  ```ts
216
- const program = Effect.gen(function*() {
217
- const repo = yield* UserRepo
218
- return yield* repo.getById("u_123")
219
- })
211
+ const program = Effect.gen(function* () {
212
+ const repo = yield* UserRepo;
213
+ return yield* repo.getById("u_123");
214
+ });
220
215
  ```
221
216
 
222
217
  or:
223
218
 
224
219
  ```ts
225
- const program = Effect.service(UserRepo).pipe(
226
- Effect.flatMap((repo) => repo.getById("u_123"))
227
- )
220
+ const program = Effect.service(UserRepo).pipe(Effect.flatMap((repo) => repo.getById("u_123")));
228
221
  ```
229
222
 
230
223
  Best practice:
@@ -239,10 +232,10 @@ Prefer keeping service access inside the business operation that needs it rather
239
232
  Avoid this pattern:
240
233
 
241
234
  ```ts
242
- export const createTodo = Effect.fn(function*(title: string) {
243
- const todos = yield* TodoService
244
- return yield* todos.create(title)
245
- })
235
+ export const createTodo = Effect.fn(function* (title: string) {
236
+ const todos = yield* TodoService;
237
+ return yield* todos.create(title);
238
+ });
246
239
  ```
247
240
 
248
241
  Why this is usually a bad pattern:
@@ -261,14 +254,14 @@ Prefer one of these patterns instead:
261
254
  Good:
262
255
 
263
256
  ```ts
264
- export const completeTodo = Effect.fn("completeTodo")(function*(id: number) {
265
- const todos = yield* TodoService
266
- const todo = yield* todos.getById(id)
257
+ export const completeTodo = Effect.fn("completeTodo")(function* (id: number) {
258
+ const todos = yield* TodoService;
259
+ const todo = yield* todos.getById(id);
267
260
  if (todo.completed) {
268
- return todo
261
+ return todo;
269
262
  }
270
- return yield* todos.setCompleted(id, true)
271
- })
263
+ return yield* todos.setCompleted(id, true);
264
+ });
272
265
  ```
273
266
 
274
267
  This is good because:
@@ -315,8 +308,8 @@ Use for pure, already-constructed implementations.
315
308
 
316
309
  ```ts
317
310
  const UserRepoTest = Layer.succeed(UserRepo)({
318
- getById: (id) => Effect.succeed({ id, name: "Test User" })
319
- })
311
+ getById: (id) => Effect.succeed({ id, name: "Test User" }),
312
+ });
320
313
  ```
321
314
 
322
315
  Use this when:
@@ -330,23 +323,26 @@ Use this when:
330
323
  Use when constructing a service requires effects, other services, or scoped resource acquisition.
331
324
 
332
325
  ```ts
333
- class Config extends Context.Service<Config, {
334
- readonly apiBaseUrl: string
335
- }>()("Config") {}
326
+ class Config extends Context.Service<
327
+ Config,
328
+ {
329
+ readonly apiBaseUrl: string;
330
+ }
331
+ >()("Config") {}
336
332
 
337
333
  const UserRepoLayer = Layer.effect(UserRepo)(
338
- Effect.gen(function*() {
339
- const config = yield* Config
334
+ Effect.gen(function* () {
335
+ const config = yield* Config;
340
336
 
341
337
  return {
342
338
  getById: (id) =>
343
339
  Effect.succeed({
344
340
  id,
345
- name: `Fetched from ${config.apiBaseUrl}`
346
- })
347
- }
348
- })
349
- )
341
+ name: `Fetched from ${config.apiBaseUrl}`,
342
+ }),
343
+ };
344
+ }),
345
+ );
350
346
  ```
351
347
 
352
348
  Use this when:
@@ -395,42 +391,51 @@ These operators do different things. Do not treat them as interchangeable.
395
391
  ### Example Services
396
392
 
397
393
  ```ts
398
- import { Context, Effect, Layer } from "effect"
394
+ import { Context, Effect, Layer } from "effect";
399
395
 
400
- class Config extends Context.Service<Config, {
401
- readonly apiBaseUrl: string
402
- }>()("Config") {}
396
+ class Config extends Context.Service<
397
+ Config,
398
+ {
399
+ readonly apiBaseUrl: string;
400
+ }
401
+ >()("Config") {}
403
402
 
404
- class Logger extends Context.Service<Logger, {
405
- readonly log: (message: string) => Effect.Effect<void>
406
- }>()("Logger") {}
403
+ class Logger extends Context.Service<
404
+ Logger,
405
+ {
406
+ readonly log: (message: string) => Effect.Effect<void>;
407
+ }
408
+ >()("Logger") {}
407
409
 
408
- class UserRepo extends Context.Service<UserRepo, {
409
- readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }>
410
- }>()("UserRepo") {}
410
+ class UserRepo extends Context.Service<
411
+ UserRepo,
412
+ {
413
+ readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }>;
414
+ }
415
+ >()("UserRepo") {}
411
416
 
412
417
  const ConfigLayer = Layer.succeed(Config)({
413
- apiBaseUrl: "https://api.example.com"
414
- })
418
+ apiBaseUrl: "https://api.example.com",
419
+ });
415
420
 
416
421
  const LoggerLayer = Layer.succeed(Logger)({
417
- log: (message) => Effect.sync(() => console.log(message))
418
- })
422
+ log: (message) => Effect.sync(() => console.log(message)),
423
+ });
419
424
 
420
425
  const UserRepoLayer = Layer.effect(UserRepo)(
421
- Effect.gen(function*() {
422
- const config = yield* Config
423
- const logger = yield* Logger
426
+ Effect.gen(function* () {
427
+ const config = yield* Config;
428
+ const logger = yield* Logger;
424
429
 
425
430
  return {
426
431
  getById: (id) =>
427
- Effect.gen(function*() {
428
- yield* logger.log(`loading ${id} from ${config.apiBaseUrl}`)
429
- return { id, name: "Ada" }
430
- })
431
- }
432
- })
433
- )
432
+ Effect.gen(function* () {
433
+ yield* logger.log(`loading ${id} from ${config.apiBaseUrl}`);
434
+ return { id, name: "Ada" };
435
+ }),
436
+ };
437
+ }),
438
+ );
434
439
  ```
435
440
 
436
441
  ### `Layer.mergeAll`
@@ -438,10 +443,7 @@ const UserRepoLayer = Layer.effect(UserRepo)(
438
443
  Use `Layer.mergeAll` to combine outputs of independent layers.
439
444
 
440
445
  ```ts
441
- const Dependencies = Layer.mergeAll(
442
- ConfigLayer,
443
- LoggerLayer
444
- )
446
+ const Dependencies = Layer.mergeAll(ConfigLayer, LoggerLayer);
445
447
  ```
446
448
 
447
449
  Use this when:
@@ -464,10 +466,7 @@ Important:
464
466
  Correct pattern:
465
467
 
466
468
  ```ts
467
- const Dependencies = Layer.mergeAll(
468
- ConfigLayer,
469
- LoggerLayer
470
- )
469
+ const Dependencies = Layer.mergeAll(ConfigLayer, LoggerLayer);
471
470
  ```
472
471
 
473
472
  ### `Layer.provide`
@@ -475,12 +474,9 @@ const Dependencies = Layer.mergeAll(
475
474
  Use `Layer.provide` to satisfy a target layer's dependencies with another layer, while keeping only the target layer's outputs.
476
475
 
477
476
  ```ts
478
- const Dependencies = Layer.mergeAll(
479
- ConfigLayer,
480
- LoggerLayer
481
- )
477
+ const Dependencies = Layer.mergeAll(ConfigLayer, LoggerLayer);
482
478
 
483
- const UserRepoLayerReady = Layer.provide(UserRepoLayer, Dependencies)
479
+ const UserRepoLayerReady = Layer.provide(UserRepoLayer, Dependencies);
484
480
  ```
485
481
 
486
482
  Interpretation:
@@ -495,12 +491,10 @@ This is the operator to use when you want to hide construction dependencies behi
495
491
  Example program:
496
492
 
497
493
  ```ts
498
- const program = Effect.gen(function*() {
499
- const repo = yield* UserRepo
500
- return yield* repo.getById("u_123")
501
- }).pipe(
502
- Effect.provide(UserRepoLayerReady)
503
- )
494
+ const program = Effect.gen(function* () {
495
+ const repo = yield* UserRepo;
496
+ return yield* repo.getById("u_123");
497
+ }).pipe(Effect.provide(UserRepoLayerReady));
504
498
  ```
505
499
 
506
500
  ### `Layer.provideMerge`
@@ -508,12 +502,9 @@ const program = Effect.gen(function*() {
508
502
  Use `provideMerge` when you want to satisfy dependencies and retain both the dependency outputs and the target outputs.
509
503
 
510
504
  ```ts
511
- const Dependencies = Layer.mergeAll(
512
- ConfigLayer,
513
- LoggerLayer
514
- )
505
+ const Dependencies = Layer.mergeAll(ConfigLayer, LoggerLayer);
515
506
 
516
- const AppLayer = Layer.provideMerge(UserRepoLayer, Dependencies)
507
+ const AppLayer = Layer.provideMerge(UserRepoLayer, Dependencies);
517
508
  ```
518
509
 
519
510
  Interpretation:
@@ -526,16 +517,14 @@ This is useful for assembling larger application layers incrementally, especiall
526
517
  Example program:
527
518
 
528
519
  ```ts
529
- const program = Effect.gen(function*() {
530
- const repo = yield* UserRepo
531
- const logger = yield* Logger
532
-
533
- const user = yield* repo.getById("u_123")
534
- yield* logger.log(user.name)
535
- return user
536
- }).pipe(
537
- Effect.provide(AppLayer)
538
- )
520
+ const program = Effect.gen(function* () {
521
+ const repo = yield* UserRepo;
522
+ const logger = yield* Logger;
523
+
524
+ const user = yield* repo.getById("u_123");
525
+ yield* logger.log(user.name);
526
+ return user;
527
+ }).pipe(Effect.provide(AppLayer));
539
528
  ```
540
529
 
541
530
  Preferred rule:
@@ -566,29 +555,18 @@ Preferred style:
566
555
  Good pattern:
567
556
 
568
557
  ```ts
569
- const UserDependencies = Layer.mergeAll(
570
- ConfigLayer,
571
- LoggerLayer
572
- )
573
-
574
- const UserLayer = Layer.provide(UserRepoLayer, UserDependencies)
575
-
576
- const BillingDependencies = Layer.mergeAll(
577
- ConfigLayer,
578
- LoggerLayer,
579
- DatabaseLayer
580
- )
581
-
582
- const BillingLayer = Layer.provide(BillingServiceLayer, BillingDependencies)
583
-
584
- const AppLayer = Layer.mergeAll(
585
- UserLayer,
586
- BillingLayer,
587
- HttpLayer
588
- ).pipe(
558
+ const UserDependencies = Layer.mergeAll(ConfigLayer, LoggerLayer);
559
+
560
+ const UserLayer = Layer.provide(UserRepoLayer, UserDependencies);
561
+
562
+ const BillingDependencies = Layer.mergeAll(ConfigLayer, LoggerLayer, DatabaseLayer);
563
+
564
+ const BillingLayer = Layer.provide(BillingServiceLayer, BillingDependencies);
565
+
566
+ const AppLayer = Layer.mergeAll(UserLayer, BillingLayer, HttpLayer).pipe(
589
567
  Layer.provide(Telemetry),
590
- Layer.provide(NodeSdk)
591
- )
568
+ Layer.provide(NodeSdk),
569
+ );
592
570
  ```
593
571
 
594
572
  Why this style is preferred:
@@ -605,10 +583,10 @@ const AppLayer = Layer.provide(
605
583
  Layer.mergeAll(
606
584
  Layer.provide(UserRepoLayer, Layer.mergeAll(ConfigLayer, LoggerLayer)),
607
585
  Layer.provide(BillingServiceLayer, Layer.mergeAll(ConfigLayer, LoggerLayer, DatabaseLayer)),
608
- HttpLayer
586
+ HttpLayer,
609
587
  ),
610
- Telemetry
611
- ).pipe(Layer.provide(NodeSdk))
588
+ Telemetry,
589
+ ).pipe(Layer.provide(NodeSdk));
612
590
  ```
613
591
 
614
592
  That style is harder to read because:
@@ -626,9 +604,9 @@ Example:
626
604
  ```ts
627
605
  const UserRepoLayerFromConfig = Layer.flatMap(ConfigLayer, (config) =>
628
606
  Layer.succeed(UserRepo)({
629
- getById: (id) => Effect.succeed({ id, name: config.apiBaseUrl })
630
- })
631
- )
607
+ getById: (id) => Effect.succeed({ id, name: config.apiBaseUrl }),
608
+ }),
609
+ );
632
610
  ```
633
611
 
634
612
  This is more specialized than `merge` or `provide`.
@@ -661,12 +639,10 @@ Bad pattern:
661
639
 
662
640
  ```ts
663
641
  const loadUser = (userId: string) =>
664
- Effect.gen(function*() {
665
- const repo = yield* UserRepo
666
- return yield* repo.getById(userId)
667
- }).pipe(
668
- Effect.provide(UserRepoLayer)
669
- )
642
+ Effect.gen(function* () {
643
+ const repo = yield* UserRepo;
644
+ return yield* repo.getById(userId);
645
+ }).pipe(Effect.provide(UserRepoLayer));
670
646
  ```
671
647
 
672
648
  Why this is an anti-pattern:
@@ -681,14 +657,12 @@ Preferred pattern:
681
657
 
682
658
  ```ts
683
659
  const loadUser = (userId: string) =>
684
- Effect.gen(function*() {
685
- const repo = yield* UserRepo
686
- return yield* repo.getById(userId)
687
- })
660
+ Effect.gen(function* () {
661
+ const repo = yield* UserRepo;
662
+ return yield* repo.getById(userId);
663
+ });
688
664
 
689
- const program = loadUser("u_123").pipe(
690
- Effect.provide(AppLayer)
691
- )
665
+ const program = loadUser("u_123").pipe(Effect.provide(AppLayer));
692
666
  ```
693
667
 
694
668
  Rule of thumb:
@@ -712,10 +686,9 @@ Typical examples:
712
686
  Preferred pattern:
713
687
 
714
688
  ```ts
715
- const runtime = ManagedRuntime.make(AppLayer)
689
+ const runtime = ManagedRuntime.make(AppLayer);
716
690
 
717
- const handleRequest = (id: string) =>
718
- runtime.runPromise(loadUser(id))
691
+ const handleRequest = (id: string) => runtime.runPromise(loadUser(id));
719
692
  ```
720
693
 
721
694
  Why:
@@ -734,9 +707,7 @@ Repo reference:
734
707
  Use `Effect.provide` to satisfy an effect's dependencies with a layer or context.
735
708
 
736
709
  ```ts
737
- const program = loadUser("u_123").pipe(
738
- Effect.provide(UserRepoLayerReady)
739
- )
710
+ const program = loadUser("u_123").pipe(Effect.provide(UserRepoLayerReady));
740
711
  ```
741
712
 
742
713
  This is the main boundary provisioning operator.
@@ -748,9 +719,9 @@ Use `provideService` for a single ad hoc implementation.
748
719
  ```ts
749
720
  const program = loadUser("u_123").pipe(
750
721
  Effect.provideService(UserRepo, {
751
- getById: (id) => Effect.succeed({ id, name: "Inline User" })
752
- })
753
- )
722
+ getById: (id) => Effect.succeed({ id, name: "Inline User" }),
723
+ }),
724
+ );
754
725
  ```
755
726
 
756
727
  Good use cases:
@@ -812,11 +783,11 @@ Good:
812
783
 
813
784
  ```ts
814
785
  const sendWelcomeEmail = (userId: string) =>
815
- Effect.gen(function*() {
816
- const repo = yield* UserRepo
817
- const user = yield* repo.getById(userId)
818
- return user
819
- })
786
+ Effect.gen(function* () {
787
+ const repo = yield* UserRepo;
788
+ const user = yield* repo.getById(userId);
789
+ return user;
790
+ });
820
791
  ```
821
792
 
822
793
  Avoid constructing `UserRepo` inside `sendWelcomeEmail`.
@@ -880,7 +851,7 @@ dependencies or configuration:
880
851
  ```ts
881
852
  // Avoid: requirements disappear from the Layer input channel.
882
853
  const makeUserRepoLayer = (config: Config, client: HttpClient) =>
883
- Layer.effect(UserRepo)(makeUserRepo(config, client))
854
+ Layer.effect(UserRepo)(makeUserRepo(config, client));
884
855
  ```
885
856
 
886
857
  Model configuration, clients, databases, clocks, platform bindings, and
@@ -890,17 +861,14 @@ outer composition boundary:
890
861
 
891
862
  ```ts
892
863
  const UserRepoLayer = Layer.effect(UserRepo)(
893
- Effect.gen(function*() {
894
- const config = yield* Config
895
- const client = yield* HttpClient
896
- return UserRepo.of(makeUserRepo(config, client))
897
- })
898
- )
899
-
900
- const AppLayer = UserRepoLayer.pipe(
901
- Layer.provide(ConfigLayer),
902
- Layer.provide(HttpClientLayer)
903
- )
864
+ Effect.gen(function* () {
865
+ const config = yield* Config;
866
+ const client = yield* HttpClient;
867
+ return UserRepo.of(makeUserRepo(config, client));
868
+ }),
869
+ );
870
+
871
+ const AppLayer = UserRepoLayer.pipe(Layer.provide(ConfigLayer), Layer.provide(HttpClientLayer));
904
872
  ```
905
873
 
906
874
  Arguments are acceptable only when they are intrinsic definitions that create
@@ -944,56 +912,60 @@ This keeps test wiring explicit and close to production composition style.
944
912
  ## Pattern: service definition plus live layer
945
913
 
946
914
  ```ts
947
- import { Context, Effect, Layer } from "effect"
915
+ import { Context, Effect, Layer } from "effect";
948
916
 
949
- class Config extends Context.Service<Config, {
950
- readonly apiBaseUrl: string
951
- }>()("Config") {}
917
+ class Config extends Context.Service<
918
+ Config,
919
+ {
920
+ readonly apiBaseUrl: string;
921
+ }
922
+ >()("Config") {}
952
923
 
953
- class UserRepo extends Context.Service<UserRepo, {
954
- readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }>
955
- }>()("UserRepo") {}
924
+ class UserRepo extends Context.Service<
925
+ UserRepo,
926
+ {
927
+ readonly getById: (id: string) => Effect.Effect<{ id: string; name: string }>;
928
+ }
929
+ >()("UserRepo") {}
956
930
 
957
931
  const ConfigLayer = Layer.succeed(Config)({
958
- apiBaseUrl: "https://api.example.com"
959
- })
932
+ apiBaseUrl: "https://api.example.com",
933
+ });
960
934
 
961
935
  const UserRepoLayer = Layer.effect(UserRepo)(
962
- Effect.gen(function*() {
963
- const config = yield* Config
936
+ Effect.gen(function* () {
937
+ const config = yield* Config;
964
938
 
965
939
  return {
966
940
  getById: (id) =>
967
941
  Effect.succeed({
968
942
  id,
969
- name: `Loaded via ${config.apiBaseUrl}`
970
- })
971
- }
972
- })
973
- )
943
+ name: `Loaded via ${config.apiBaseUrl}`,
944
+ }),
945
+ };
946
+ }),
947
+ );
974
948
 
975
- const Dependencies = Layer.mergeAll(ConfigLayer)
949
+ const Dependencies = Layer.mergeAll(ConfigLayer);
976
950
 
977
- const AppLayer = Layer.provide(UserRepoLayer, Dependencies)
951
+ const AppLayer = Layer.provide(UserRepoLayer, Dependencies);
978
952
  ```
979
953
 
980
954
  ## Pattern: provide at the top level
981
955
 
982
956
  ```ts
983
- const program = Effect.gen(function*() {
984
- const repo = yield* UserRepo
985
- return yield* repo.getById("u_123")
986
- }).pipe(
987
- Effect.provide(AppLayer)
988
- )
957
+ const program = Effect.gen(function* () {
958
+ const repo = yield* UserRepo;
959
+ return yield* repo.getById("u_123");
960
+ }).pipe(Effect.provide(AppLayer));
989
961
  ```
990
962
 
991
963
  ## Pattern: single-service override in tests
992
964
 
993
965
  ```ts
994
966
  const TestRepo = Layer.succeed(UserRepo)({
995
- getById: (id) => Effect.succeed({ id, name: "Test" })
996
- })
967
+ getById: (id) => Effect.succeed({ id, name: "Test" }),
968
+ });
997
969
  ```
998
970
 
999
971
  ## Anti-Patterns