alchemy-effect 0.4.0 → 0.5.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 (73) hide show
  1. package/bin/alchemy-effect.js +295 -253
  2. package/bin/alchemy-effect.js.map +1 -1
  3. package/lib/apply.d.ts.map +1 -1
  4. package/lib/apply.js +237 -232
  5. package/lib/apply.js.map +1 -1
  6. package/lib/aws/dynamodb/table.provider.d.ts.map +1 -1
  7. package/lib/aws/dynamodb/table.provider.js +10 -2
  8. package/lib/aws/dynamodb/table.provider.js.map +1 -1
  9. package/lib/aws/ec2/vpc.provider.d.ts +2 -2
  10. package/lib/aws/ec2/vpc.provider.d.ts.map +1 -1
  11. package/lib/aws/ec2/vpc.provider.js +6 -7
  12. package/lib/aws/ec2/vpc.provider.js.map +1 -1
  13. package/lib/aws/lambda/function.provider.d.ts.map +1 -1
  14. package/lib/aws/lambda/function.provider.js +19 -23
  15. package/lib/aws/lambda/function.provider.js.map +1 -1
  16. package/lib/aws/sqs/queue.provider.d.ts +1 -2
  17. package/lib/aws/sqs/queue.provider.d.ts.map +1 -1
  18. package/lib/aws/sqs/queue.provider.js +14 -7
  19. package/lib/aws/sqs/queue.provider.js.map +1 -1
  20. package/lib/cli/index.d.ts +7 -3
  21. package/lib/cli/index.d.ts.map +1 -1
  22. package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -1
  23. package/lib/cloudflare/kv/namespace.provider.js +11 -6
  24. package/lib/cloudflare/kv/namespace.provider.js.map +1 -1
  25. package/lib/cloudflare/r2/bucket.binding.js +1 -1
  26. package/lib/cloudflare/r2/bucket.binding.js.map +1 -1
  27. package/lib/cloudflare/r2/bucket.d.ts +1 -1
  28. package/lib/cloudflare/r2/bucket.d.ts.map +1 -1
  29. package/lib/cloudflare/r2/bucket.provider.d.ts +1 -2
  30. package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -1
  31. package/lib/cloudflare/r2/bucket.provider.js +20 -14
  32. package/lib/cloudflare/r2/bucket.provider.js.map +1 -1
  33. package/lib/cloudflare/worker/worker.d.ts +2 -2
  34. package/lib/cloudflare/worker/worker.d.ts.map +1 -1
  35. package/lib/cloudflare/worker/worker.provider.d.ts +1 -2
  36. package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -1
  37. package/lib/cloudflare/worker/worker.provider.js +40 -13
  38. package/lib/cloudflare/worker/worker.provider.js.map +1 -1
  39. package/lib/instance-id.d.ts +5 -1
  40. package/lib/instance-id.d.ts.map +1 -1
  41. package/lib/instance-id.js +4 -0
  42. package/lib/instance-id.js.map +1 -1
  43. package/lib/physical-name.d.ts +15 -4
  44. package/lib/physical-name.d.ts.map +1 -1
  45. package/lib/physical-name.js +12 -3
  46. package/lib/physical-name.js.map +1 -1
  47. package/lib/plan.d.ts.map +1 -1
  48. package/lib/plan.js +65 -17
  49. package/lib/plan.js.map +1 -1
  50. package/lib/provider.d.ts +0 -1
  51. package/lib/provider.d.ts.map +1 -1
  52. package/lib/provider.js.map +1 -1
  53. package/lib/resource.d.ts +3 -2
  54. package/lib/resource.d.ts.map +1 -1
  55. package/lib/resource.js.map +1 -1
  56. package/lib/tsconfig.test.tsbuildinfo +1 -1
  57. package/package.json +1 -1
  58. package/src/apply.ts +296 -286
  59. package/src/aws/dynamodb/table.provider.ts +15 -4
  60. package/src/aws/ec2/vpc.provider.ts +10 -9
  61. package/src/aws/lambda/function.provider.ts +42 -31
  62. package/src/aws/sqs/queue.provider.ts +15 -9
  63. package/src/cloudflare/kv/namespace.provider.ts +18 -14
  64. package/src/cloudflare/r2/bucket.binding.ts +1 -1
  65. package/src/cloudflare/r2/bucket.provider.ts +34 -30
  66. package/src/cloudflare/r2/bucket.ts +1 -1
  67. package/src/cloudflare/worker/worker.provider.ts +39 -13
  68. package/src/cloudflare/worker/worker.ts +2 -2
  69. package/src/instance-id.ts +5 -1
  70. package/src/physical-name.ts +27 -5
  71. package/src/plan.ts +90 -29
  72. package/src/provider.ts +0 -1
  73. package/src/resource.ts +17 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy-effect",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Sam Goodwin <sam@alchemy.run>",
6
6
  "homepage": "https://alchemy.run",
package/src/apply.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  type ScopedPlanStatusSession,
10
10
  } from "./cli/service.ts";
11
11
  import type { ApplyStatus } from "./event.ts";
12
- import { generateInstanceId } from "./instance-id.ts";
12
+ import { generateInstanceId, InstanceId } from "./instance-id.ts";
13
13
  import * as Output from "./output.ts";
14
14
  import {
15
15
  type Apply,
@@ -37,6 +37,7 @@ import {
37
37
  } from "./state.ts";
38
38
  import { asEffect } from "./util.ts";
39
39
  import { getProviderByType } from "./provider.ts";
40
+ import { Layer } from "effect";
40
41
 
41
42
  export type ApplyEffect<
42
43
  P extends IPlan,
@@ -332,351 +333,360 @@ const expandAndPivot = Effect.fnUntraced(function* (
332
333
  );
333
334
  });
334
335
 
335
- if (node.action === "create") {
336
- const news = (yield* Output.evaluate(
337
- node.props,
338
- upstream,
339
- )) as Record<string, any>;
336
+ const apply = Effect.gen(function* () {
337
+ if (node.action === "create") {
338
+ const news = (yield* Output.evaluate(
339
+ node.props,
340
+ upstream,
341
+ )) as Record<string, any>;
340
342
 
341
- const checkpoint = (attr: any) =>
342
- commit<CreatingResourceState>({
343
- status: "creating",
344
- logicalId: id,
345
- instanceId,
346
- resourceType: node.resource.type,
347
- props: news,
348
- attr,
349
- providerVersion: node.provider.version ?? 0,
343
+ const checkpoint = (attr: any) =>
344
+ commit<CreatingResourceState>({
345
+ status: "creating",
346
+ logicalId: id,
347
+ instanceId,
348
+ resourceType: node.resource.type,
349
+ props: news,
350
+ attr,
351
+ providerVersion: node.provider.version ?? 0,
352
+ bindings: node.bindings,
353
+ downstream: node.downstream,
354
+ });
355
+
356
+ if (!node.state) {
357
+ yield* checkpoint(undefined);
358
+ }
359
+
360
+ let attr: any;
361
+ if (
362
+ node.action === "create" &&
363
+ node.provider.precreate &&
364
+ // pre-create is only designed to ensure the resource exists, if we have state.attr, then it already exists and should be skipped
365
+ node.state?.attr === undefined
366
+ ) {
367
+ yield* report("pre-creating");
368
+
369
+ // stub the resource prior to resolving upstream resources or bindings if a stub is available
370
+ attr = yield* node.provider.precreate({
371
+ id,
372
+ news: node.props,
373
+ session: scopedSession,
374
+ instanceId,
375
+ });
376
+
377
+ yield* checkpoint(attr);
378
+ }
379
+
380
+ yield* report("attaching");
381
+
382
+ let bindingOutputs = yield* attachBindings({
383
+ resource,
350
384
  bindings: node.bindings,
351
- downstream: node.downstream,
385
+ target: {
386
+ id,
387
+ props: news,
388
+ attr,
389
+ },
352
390
  });
353
391
 
354
- if (!node.state) {
355
- yield* checkpoint(undefined);
356
- }
392
+ yield* report("creating");
357
393
 
358
- let attr: any;
359
- if (
360
- node.action === "create" &&
361
- node.provider.precreate &&
362
- // pre-create is only designed to ensure the resource exists, if we have state.attr, then it already exists and should be skipped
363
- node.state?.attr === undefined
364
- ) {
365
- yield* report("pre-creating");
366
-
367
- // stub the resource prior to resolving upstream resources or bindings if a stub is available
368
- attr = yield* node.provider.precreate({
394
+ attr = yield* node.provider.create({
369
395
  id,
370
- news: node.props,
371
- session: scopedSession,
396
+ news,
372
397
  instanceId,
398
+ bindings: bindingOutputs,
399
+ session: scopedSession,
373
400
  });
374
401
 
375
402
  yield* checkpoint(attr);
376
- }
377
403
 
378
- yield* report("attaching");
404
+ yield* report("post-attach");
405
+ bindingOutputs = yield* postAttachBindings({
406
+ resource,
407
+ bindings: node.bindings,
408
+ bindingOutputs,
409
+ target: {
410
+ id,
411
+ props: news,
412
+ attr,
413
+ },
414
+ });
379
415
 
380
- let bindingOutputs = yield* attachBindings({
381
- resource,
382
- bindings: node.bindings,
383
- target: {
384
- id,
416
+ yield* commit<CreatedResourceState>({
417
+ status: "created",
418
+ logicalId: id,
419
+ instanceId,
420
+ resourceType: node.resource.type,
385
421
  props: news,
386
422
  attr,
387
- },
388
- });
389
-
390
- yield* report("creating");
423
+ bindings: node.bindings.map((binding, i) => ({
424
+ ...binding,
425
+ attr: bindingOutputs[i],
426
+ })),
427
+ providerVersion: node.provider.version ?? 0,
428
+ downstream: node.downstream,
429
+ });
391
430
 
392
- attr = yield* node.provider.create({
393
- id,
394
- news,
395
- instanceId,
396
- bindings: bindingOutputs,
397
- session: scopedSession,
398
- });
431
+ yield* report("created");
432
+
433
+ return attr;
434
+ } else if (node.action === "update") {
435
+ const upstream = Object.fromEntries(
436
+ yield* Effect.all(
437
+ Object.entries(Output.resolveUpstream(node.props)).map(
438
+ ([id]) =>
439
+ resolveUpstream(id).pipe(
440
+ Effect.map(({ upstreamAttr }) => [id, upstreamAttr]),
441
+ ),
442
+ ),
443
+ ),
444
+ );
445
+ const news = (yield* Output.evaluate(
446
+ node.props,
447
+ upstream,
448
+ )) as Record<string, any>;
449
+
450
+ const checkpoint = (attr: any) => {
451
+ if (node.state.status === "replaced") {
452
+ return commit<ReplacedResourceState>({
453
+ ...node.state,
454
+ attr,
455
+ props: news,
456
+ });
457
+ } else {
458
+ return commit<UpdatingReourceState>({
459
+ status: "updating",
460
+ logicalId: id,
461
+ instanceId,
462
+ resourceType: node.resource.type,
463
+ props: news,
464
+ attr,
465
+ providerVersion: node.provider.version ?? 0,
466
+ bindings: node.bindings,
467
+ downstream: node.downstream,
468
+ old:
469
+ node.state.status === "updating"
470
+ ? node.state.old
471
+ : node.state,
472
+ });
473
+ }
474
+ };
475
+
476
+ yield* checkpoint(node.state.attr);
477
+
478
+ yield* report("attaching");
479
+
480
+ let bindingOutputs = yield* attachBindings({
481
+ resource,
482
+ bindings: node.bindings,
483
+ target: {
484
+ id,
485
+ props: news,
486
+ attr: node.state.attr,
487
+ },
488
+ });
399
489
 
400
- yield* checkpoint(attr);
490
+ yield* report("updating");
401
491
 
402
- yield* report("post-attach");
403
- bindingOutputs = yield* postAttachBindings({
404
- resource,
405
- bindings: node.bindings,
406
- bindingOutputs,
407
- target: {
492
+ const attr = yield* node.provider.update({
408
493
  id,
409
- props: news,
410
- attr,
411
- },
412
- });
494
+ news,
495
+ instanceId,
496
+ bindings: bindingOutputs,
497
+ session: scopedSession,
498
+ olds:
499
+ node.state.status === "created" ||
500
+ node.state.status === "updated" ||
501
+ node.state.status === "replaced"
502
+ ? node.state.props
503
+ : node.state.old.props,
504
+ output: node.state.attr,
505
+ });
413
506
 
414
- yield* commit<CreatedResourceState>({
415
- status: "created",
416
- logicalId: id,
417
- instanceId,
418
- resourceType: node.resource.type,
419
- props: news,
420
- attr,
421
- bindings: node.bindings.map((binding, i) => ({
422
- ...binding,
423
- attr: bindingOutputs[i],
424
- })),
425
- providerVersion: node.provider.version ?? 0,
426
- downstream: node.downstream,
427
- });
507
+ yield* checkpoint(attr);
428
508
 
429
- yield* report("created");
509
+ yield* report("post-attach");
430
510
 
431
- return attr;
432
- } else if (node.action === "update") {
433
- const upstream = Object.fromEntries(
434
- yield* Effect.all(
435
- Object.entries(Output.resolveUpstream(node.props)).map(([id]) =>
436
- resolveUpstream(id).pipe(
437
- Effect.map(({ upstreamAttr }) => [id, upstreamAttr]),
438
- ),
439
- ),
440
- ),
441
- );
442
- const news = (yield* Output.evaluate(
443
- node.props,
444
- upstream,
445
- )) as Record<string, any>;
511
+ bindingOutputs = yield* postAttachBindings({
512
+ resource,
513
+ bindings: node.bindings,
514
+ bindingOutputs,
515
+ target: {
516
+ id,
517
+ props: news,
518
+ attr,
519
+ },
520
+ });
446
521
 
447
- const checkpoint = (attr: any) => {
448
522
  if (node.state.status === "replaced") {
449
- return commit<ReplacedResourceState>({
523
+ yield* commit<ReplacedResourceState>({
450
524
  ...node.state,
451
525
  attr,
452
526
  props: news,
453
527
  });
454
528
  } else {
455
- return commit<UpdatingReourceState>({
456
- status: "updating",
529
+ yield* commit<UpdatedResourceState>({
530
+ status: "updated",
457
531
  logicalId: id,
458
532
  instanceId,
459
533
  resourceType: node.resource.type,
460
534
  props: news,
461
535
  attr,
536
+ bindings: node.bindings.map((binding, i) => ({
537
+ ...binding,
538
+ attr: bindingOutputs[i],
539
+ })),
462
540
  providerVersion: node.provider.version ?? 0,
463
- bindings: node.bindings,
464
541
  downstream: node.downstream,
465
- old:
466
- node.state.status === "updating"
467
- ? node.state.old
468
- : node.state,
469
542
  });
470
543
  }
471
- };
472
544
 
473
- yield* checkpoint(node.state.attr);
474
-
475
- yield* report("attaching");
476
-
477
- let bindingOutputs = yield* attachBindings({
478
- resource,
479
- bindings: node.bindings,
480
- target: {
481
- id,
482
- props: news,
483
- attr: node.state.attr,
484
- },
485
- });
545
+ yield* report("updated");
486
546
 
487
- yield* report("updating");
547
+ return attr;
548
+ } else if (node.action === "replace") {
549
+ if (node.state.status === "replaced") {
550
+ // we've already created the replacement resource, return the output
551
+ return node.state.attr;
552
+ }
553
+ let state: ReplacingResourceState;
554
+ if (node.state.status !== "replacing") {
555
+ yield* commit<ReplacingResourceState>(
556
+ (state = {
557
+ status: "replacing",
558
+ logicalId: id,
559
+ instanceId,
560
+ resourceType: node.resource.type,
561
+ props: node.props,
562
+ attr: node.state.attr,
563
+ providerVersion: node.provider.version ?? 0,
564
+ deleteFirst: node.deleteFirst,
565
+ old: node.state,
566
+ downstream: node.downstream,
567
+ }),
568
+ );
569
+ } else {
570
+ state = node.state;
571
+ }
572
+ const upstream = Object.fromEntries(
573
+ yield* Effect.all(
574
+ Object.entries(Output.resolveUpstream(node.props)).map(
575
+ ([id]) =>
576
+ resolveUpstream(id).pipe(
577
+ Effect.map(({ upstreamAttr }) => [id, upstreamAttr]),
578
+ ),
579
+ ),
580
+ ),
581
+ );
582
+ const news = (yield* Output.evaluate(
583
+ node.props,
584
+ upstream,
585
+ )) as Record<string, any>;
586
+
587
+ const checkpoint = <
588
+ S extends ReplacingResourceState | ReplacedResourceState,
589
+ >({
590
+ status,
591
+ attr,
592
+ bindings,
593
+ }: Pick<S, "status" | "attr" | "bindings">) =>
594
+ commit<S>({
595
+ status,
596
+ logicalId: id,
597
+ instanceId,
598
+ resourceType: node.resource.type,
599
+ props: news,
600
+ attr,
601
+ providerVersion: node.provider.version ?? 0,
602
+ bindings: bindings ?? node.bindings,
603
+ downstream: node.downstream,
604
+ old: state.old,
605
+ deleteFirst: node.deleteFirst,
606
+ } as S);
488
607
 
489
- const attr = yield* node.provider.update({
490
- id,
491
- news,
492
- instanceId,
493
- bindings: bindingOutputs,
494
- session: scopedSession,
495
- olds:
496
- node.state.status === "created" ||
497
- node.state.status === "updated" ||
498
- node.state.status === "replaced"
499
- ? node.state.props
500
- : node.state.old.props,
501
- output: node.state.attr,
502
- });
608
+ let attr: any;
609
+ if (
610
+ node.provider.precreate &&
611
+ // pre-create is only designed to ensure the resource exists, if we have state.attr, then it already exists and should be skipped
612
+ node.state?.attr === undefined
613
+ ) {
614
+ yield* report("pre-creating");
503
615
 
504
- yield* checkpoint(attr);
616
+ // stub the resource prior to resolving upstream resources or bindings if a stub is available
617
+ attr = yield* node.provider.precreate({
618
+ id,
619
+ news: node.props,
620
+ session: scopedSession,
621
+ instanceId,
622
+ });
505
623
 
506
- yield* report("post-attach");
624
+ yield* checkpoint({
625
+ status: "replacing",
626
+ attr,
627
+ });
628
+ }
507
629
 
508
- bindingOutputs = yield* postAttachBindings({
509
- resource,
510
- bindings: node.bindings,
511
- bindingOutputs,
512
- target: {
513
- id,
514
- props: news,
515
- attr,
516
- },
517
- });
630
+ yield* report("attaching");
518
631
 
519
- if (node.state.status === "replaced") {
520
- yield* commit<ReplacedResourceState>({
521
- ...node.state,
522
- attr,
523
- props: news,
524
- });
525
- } else {
526
- yield* commit<UpdatedResourceState>({
527
- status: "updated",
528
- logicalId: id,
529
- instanceId,
530
- resourceType: node.resource.type,
531
- props: news,
532
- attr,
533
- bindings: node.bindings.map((binding, i) => ({
534
- ...binding,
535
- attr: bindingOutputs[i],
536
- })),
537
- providerVersion: node.provider.version ?? 0,
538
- downstream: node.downstream,
632
+ let bindingOutputs = yield* attachBindings({
633
+ resource,
634
+ bindings: node.bindings,
635
+ target: {
636
+ id,
637
+ props: news,
638
+ attr,
639
+ },
539
640
  });
540
- }
541
641
 
542
- yield* report("updated");
642
+ yield* report("creating replacement");
543
643
 
544
- return attr;
545
- } else if (node.action === "replace") {
546
- if (node.state.status === "replaced") {
547
- // we've already created the replacement resource, return the output
548
- return node.state.attr;
549
- }
550
- let state: ReplacingResourceState;
551
- if (node.state.status !== "replacing") {
552
- yield* commit<ReplacingResourceState>(
553
- (state = {
554
- status: "replacing",
555
- logicalId: id,
556
- instanceId,
557
- resourceType: node.resource.type,
558
- props: node.props,
559
- attr: node.state.attr,
560
- providerVersion: node.provider.version ?? 0,
561
- deleteFirst: node.deleteFirst,
562
- old: node.state,
563
- downstream: node.downstream,
564
- }),
565
- );
566
- } else {
567
- state = node.state;
568
- }
569
- const upstream = Object.fromEntries(
570
- yield* Effect.all(
571
- Object.entries(Output.resolveUpstream(node.props)).map(([id]) =>
572
- resolveUpstream(id).pipe(
573
- Effect.map(({ upstreamAttr }) => [id, upstreamAttr]),
574
- ),
575
- ),
576
- ),
577
- );
578
- const news = (yield* Output.evaluate(
579
- node.props,
580
- upstream,
581
- )) as Record<string, any>;
582
-
583
- const checkpoint = <
584
- S extends ReplacingResourceState | ReplacedResourceState,
585
- >({
586
- status,
587
- attr,
588
- bindings,
589
- }: Pick<S, "status" | "attr" | "bindings">) =>
590
- commit<S>({
591
- status,
592
- logicalId: id,
593
- instanceId,
594
- resourceType: node.resource.type,
595
- props: news,
596
- attr,
597
- providerVersion: node.provider.version ?? 0,
598
- bindings: bindings ?? node.bindings,
599
- downstream: node.downstream,
600
- old: state.old,
601
- deleteFirst: node.deleteFirst,
602
- } as S);
603
-
604
- let attr: any;
605
- if (
606
- node.provider.precreate &&
607
- // pre-create is only designed to ensure the resource exists, if we have state.attr, then it already exists and should be skipped
608
- node.state?.attr === undefined
609
- ) {
610
- yield* report("pre-creating");
611
-
612
- // stub the resource prior to resolving upstream resources or bindings if a stub is available
613
- attr = yield* node.provider.precreate({
644
+ attr = yield* node.provider.create({
614
645
  id,
615
- news: node.props,
616
- session: scopedSession,
646
+ news,
617
647
  instanceId,
648
+ bindings: bindingOutputs,
649
+ session: scopedSession,
618
650
  });
619
651
 
620
652
  yield* checkpoint({
621
653
  status: "replacing",
622
654
  attr,
623
655
  });
624
- }
625
656
 
626
- yield* report("attaching");
657
+ yield* report("post-attach");
627
658
 
628
- let bindingOutputs = yield* attachBindings({
629
- resource,
630
- bindings: node.bindings,
631
- target: {
632
- id,
633
- props: news,
634
- attr,
635
- },
636
- });
637
-
638
- yield* report("creating replacement");
639
-
640
- attr = yield* node.provider.create({
641
- id,
642
- news,
643
- instanceId,
644
- bindings: bindingOutputs,
645
- session: scopedSession,
646
- });
647
-
648
- yield* checkpoint({
649
- status: "replacing",
650
- attr,
651
- });
652
-
653
- yield* report("post-attach");
659
+ bindingOutputs = yield* postAttachBindings({
660
+ resource,
661
+ bindings: node.bindings,
662
+ bindingOutputs,
663
+ target: {
664
+ id,
665
+ props: news,
666
+ attr,
667
+ },
668
+ });
654
669
 
655
- bindingOutputs = yield* postAttachBindings({
656
- resource,
657
- bindings: node.bindings,
658
- bindingOutputs,
659
- target: {
660
- id,
661
- props: news,
670
+ yield* checkpoint<ReplacedResourceState>({
671
+ status: "replaced",
662
672
  attr,
663
- },
664
- });
673
+ bindings: node.bindings.map((binding, i) => ({
674
+ ...binding,
675
+ attr: bindingOutputs[i],
676
+ })),
677
+ });
665
678
 
666
- yield* checkpoint<ReplacedResourceState>({
667
- status: "replaced",
668
- attr,
669
- bindings: node.bindings.map((binding, i) => ({
670
- ...binding,
671
- attr: bindingOutputs[i],
672
- })),
673
- });
679
+ yield* report("created");
680
+ return attr;
681
+ }
682
+ // @ts-expect-error
683
+ return yield* Effect.dieMessage(`Unknown action: ${node.action}`);
684
+ });
674
685
 
675
- yield* report("created");
676
- return attr;
677
- }
678
- // @ts-expect-error
679
- return yield* Effect.dieMessage(`Unknown action: ${node.action}`);
686
+ // provide the resource-specific context (InstanceId, etc.)
687
+ return yield* apply.pipe(
688
+ Effect.provide(Layer.succeed(InstanceId, instanceId)),
689
+ );
680
690
  }),
681
691
  ));
682
692
  }) as Effect.Effect<any, never, never>;
@@ -835,7 +845,7 @@ const collectGarbage = Effect.fnUntraced(function* (
835
845
  });
836
846
  yield* report("replaced");
837
847
  }
838
- }),
848
+ }).pipe(Effect.provide(Layer.succeed(InstanceId, instanceId))),
839
849
  ));
840
850
  },
841
851
  );