From 0ee61845b9efc25ce0d290fdd93ecf52fb78440f Mon Sep 17 00:00:00 2001 From: Taras Mankovski <74687+taras@users.noreply.github.com> Date: Wed, 15 Jul 2026 00:31:16 -0400 Subject: [PATCH 1/2] chore(deps): align EffectionX 0.8 set, adopt published context-api, drop vendor fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade the @effectionx/* packages to the coordinated 0.8-era release set, pinned exact in both package.json and deno.json so Deno and pnpm resolve identical versions (this also removes the @effectionx/node drift where pnpm resolved 0.2.3 but Deno 0.2.2): converge 0.1.4, fetch 0.2.0, fs 0.3.0, middleware 0.1.1, node 0.2.4, process 0.8.1, scope-eval 0.1.3, stream-helpers 0.8.3, test-adapter 0.7.4, timebox 0.4.3 Replace the vendored @effectionx/context-api fork (0.5.0-vendored) with the published 0.6.0, which ships the nested-scope .around() middleware behavior ({ at: "min" } innermost-wins) that the fork was created for. Remove vendor/context-api from every workspace list, import map, and tsconfig path, and stop passing vendor/ to oxfmt. effection stays pinned at 4.1.0-alpha.7: alpha.9 has a scope-teardown regression (scope destructors run in registration order instead of reverse, deadlocking @effectionx/process's kill+drain teardown) that is fixed upstream by https://github.com/thefrontside/effection/pull/1215 but not yet released. The other alpha.9 blocker — effect.enter() errors becoming uncatchable — is already fixed on the v4-1-alpha branch (#1179). Once a release ships with both, bumping the pin is a one-line change. --- core/deno.json | 2 +- core/package.json | 2 +- deno.json | 24 ++--- deno.lock | 133 ++++++++++++++++----------- package.json | 26 +++--- pnpm-lock.yaml | 154 +++++++++++++++---------------- pnpm-workspace.yaml | 1 - runtime/package.json | 2 +- tsconfig.node.json | 2 - vendor/context-api/mod.ts | 158 -------------------------------- vendor/context-api/package.json | 6 -- 11 files changed, 182 insertions(+), 328 deletions(-) delete mode 100644 vendor/context-api/mod.ts delete mode 100644 vendor/context-api/package.json diff --git a/core/deno.json b/core/deno.json index cdbf87a..c1fca5d 100644 --- a/core/deno.json +++ b/core/deno.json @@ -7,7 +7,7 @@ "imports": { "@executablemd/durable-streams": "../durable-streams/mod.ts", "@executablemd/runtime": "../runtime/mod.ts", - "@effectionx/context-api": "../vendor/context-api/mod.ts", + "@effectionx/context-api": "npm:@effectionx/context-api@0.6.0", "acorn": "npm:acorn@^8.16.0", "gray-matter": "npm:gray-matter@^4.0.3", "magic-string": "npm:magic-string@^0.30.21", diff --git a/core/package.json b/core/package.json index 5161419..424c13c 100644 --- a/core/package.json +++ b/core/package.json @@ -8,6 +8,6 @@ "dependencies": { "@executablemd/durable-streams": "workspace:*", "@executablemd/runtime": "workspace:*", - "@effectionx/context-api": "workspace:*" + "@effectionx/context-api": "0.6.0" } } diff --git a/deno.json b/deno.json index 39200fd..908a303 100644 --- a/deno.json +++ b/deno.json @@ -6,23 +6,23 @@ "@durable-streams/client": "npm:@durable-streams/client@^0.2.2", "@effectionx/bdd/node": "./test-support/bdd.ts", "@effectionx/bdd/expect": "./test-support/expect.ts", - "@effectionx/test-adapter": "npm:@effectionx/test-adapter@^0.7.3", + "@effectionx/test-adapter": "npm:@effectionx/test-adapter@0.7.4", "effection": "npm:effection@4.1.0-alpha.7", "effection/experimental": "npm:effection@4.1.0-alpha.7/experimental", "@executablemd/durable-streams": "./durable-streams/mod.ts", "@executablemd/runtime": "./runtime/mod.ts", "@executablemd/runtime/test": "./runtime/test/mod.ts", "@executablemd/code-review-agent": "./packages/code-review-agent/mod.ts", - "@effectionx/context-api": "./vendor/context-api/mod.ts", - "@effectionx/converge": "npm:@effectionx/converge@^0.1.3", - "@effectionx/fetch": "npm:@effectionx/fetch@^0.1.2", - "@effectionx/fs": "npm:@effectionx/fs@0.2.2", - "@effectionx/middleware": "npm:@effectionx/middleware@0.1.0", - "@effectionx/node": "npm:@effectionx/node@^0.2.2", - "@effectionx/process": "npm:@effectionx/process@^0.7.3", - "@effectionx/scope-eval": "npm:@effectionx/scope-eval@^0.1.2", - "@effectionx/stream-helpers": "npm:@effectionx/stream-helpers@^0.8.1", - "@effectionx/timebox": "npm:@effectionx/timebox@^0.4.2", + "@effectionx/context-api": "npm:@effectionx/context-api@0.6.0", + "@effectionx/converge": "npm:@effectionx/converge@0.1.4", + "@effectionx/fetch": "npm:@effectionx/fetch@0.2.0", + "@effectionx/fs": "npm:@effectionx/fs@0.3.0", + "@effectionx/middleware": "npm:@effectionx/middleware@0.1.1", + "@effectionx/node": "npm:@effectionx/node@0.2.4", + "@effectionx/process": "npm:@effectionx/process@0.8.1", + "@effectionx/scope-eval": "npm:@effectionx/scope-eval@0.1.3", + "@effectionx/stream-helpers": "npm:@effectionx/stream-helpers@0.8.3", + "@effectionx/timebox": "npm:@effectionx/timebox@0.4.3", "configliere": "npm:configliere@^0.2.3", "expect": "npm:expect@^30", "@std/expect": "npm:expect@^30", @@ -37,7 +37,7 @@ "build": "deno compile --node-modules-dir=none --exclude-unused-npm --exclude .opencode --exclude .internal --allow-all --output dist/xmd cli/src/cli.ts", "test": "deno test --allow-all core/tests/ durable-streams/tests/ packages/code-review-agent/tests/", "check": "deno check core/mod.ts", - "lint": "npx oxlint -c .oxlintrc.json core/src/ cli/src/ durable-streams/ runtime/ && npx oxfmt --check core/src/ cli/src/ durable-streams/ runtime/ vendor/ test-support/", + "lint": "npx oxlint -c .oxlintrc.json core/src/ cli/src/ durable-streams/ runtime/ && npx oxfmt --check core/src/ cli/src/ durable-streams/ runtime/ test-support/", "review": "deno run --allow-all cli/src/cli.ts run .reviews/ReviewPR.md --component-dir .reviews/components --component-dir .reviews/policies --component-dir core/components -j .reviews/journal.jsonl", "review:local": "deno run --allow-all cli/src/cli.ts run .reviews/ReviewPR.local.md --component-dir .reviews/components --component-dir .reviews/policies --component-dir core/components -j .reviews/journal.local.jsonl", "analyze": "deno run --allow-all cli/src/cli.ts run .reviews/AnalyzeRepo.md --component-dir .reviews/components --component-dir .reviews/policies --component-dir core/components -j .reviews/journal.analyze.jsonl", diff --git a/deno.lock b/deno.lock index 6a96cae..9a39844 100644 --- a/deno.lock +++ b/deno.lock @@ -34,16 +34,17 @@ "npm:@babel/core@^7.28.0": "7.29.7", "npm:@babel/preset-react@^7.27.1": "7.29.7_@babel+core@7.29.7", "npm:@durable-streams/client@~0.2.2": "0.2.2", - "npm:@effectionx/converge@~0.1.3": "0.1.3_effection@4.1.0-alpha.7", - "npm:@effectionx/fetch@~0.1.2": "0.1.2_effection@4.1.0-alpha.7", - "npm:@effectionx/fs@0.2.2": "0.2.2_effection@4.1.0-alpha.7", - "npm:@effectionx/middleware@0.1.0": "0.1.0", - "npm:@effectionx/node@~0.2.2": "0.2.2_effection@4.1.0-alpha.7", - "npm:@effectionx/process@~0.7.3": "0.7.3_effection@4.1.0-alpha.7", - "npm:@effectionx/scope-eval@~0.1.2": "0.1.2_effection@4.1.0-alpha.7", - "npm:@effectionx/stream-helpers@~0.8.1": "0.8.1_effection@4.1.0-alpha.7", - "npm:@effectionx/test-adapter@~0.7.3": "0.7.3_effection@4.1.0-alpha.7", - "npm:@effectionx/timebox@~0.4.2": "0.4.2_effection@4.1.0-alpha.7", + "npm:@effectionx/context-api@0.6.0": "0.6.0_effection@4.1.0-alpha.7", + "npm:@effectionx/converge@0.1.4": "0.1.4_effection@4.1.0-alpha.7", + "npm:@effectionx/fetch@0.2.0": "0.2.0_effection@4.1.0-alpha.7", + "npm:@effectionx/fs@0.3.0": "0.3.0_effection@4.1.0-alpha.7", + "npm:@effectionx/middleware@0.1.1": "0.1.1", + "npm:@effectionx/node@0.2.4": "0.2.4_effection@4.1.0-alpha.7", + "npm:@effectionx/process@0.8.1": "0.8.1_effection@4.1.0-alpha.7", + "npm:@effectionx/scope-eval@0.1.3": "0.1.3_effection@4.1.0-alpha.7", + "npm:@effectionx/stream-helpers@0.8.3": "0.8.3_effection@4.1.0-alpha.7", + "npm:@effectionx/test-adapter@0.7.4": "0.7.4_effection@4.1.0-alpha.7", + "npm:@effectionx/timebox@0.4.3": "0.4.3_effection@4.1.0-alpha.7", "npm:@opencode-ai/plugin@1.2.27": "1.2.27", "npm:@opentelemetry/api@^1.9.0": "1.9.1", "npm:@preact/signals@^2.5.1": "2.9.3_preact@10.29.7__preact-render-to-string@6.7.0_preact-render-to-string@6.7.0__preact@10.29.7", @@ -412,59 +413,70 @@ ], "bin": true }, - "@effectionx/converge@0.1.3_effection@4.1.0-alpha.7": { - "integrity": "sha512-LPuDslL53kA8etLgO/sMmqv9v66txOAO5d6DUWLnwZa6CwA2MTYkHEnZAoIGCnQYbjKTbPxlKatHgF15ihB4zA==", + "@effectionx/context-api@0.6.0_effection@4.1.0-alpha.7": { + "integrity": "sha512-t004qvlkJDMB6EhHP1lOQ97PeIn90m7cv4+wsRPnx4YBem+pJzTL+Sm1KWbKMjMeFJz4oqllUWuBJZsCi+nuTw==", + "dependencies": [ + "@effectionx/middleware", + "effection" + ] + }, + "@effectionx/converge@0.1.4_effection@4.1.0-alpha.7": { + "integrity": "sha512-M11KU7jK3gOFGI4RT+Bf6ITMJntzzoGEO2KPx9r8uBoR+Rgwiyeuq+OeIHkuiHLUC+bB1g93KOj7aKR/G0F1/Q==", "dependencies": [ "@effectionx/timebox", "effection" ] }, - "@effectionx/fetch@0.1.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-CzoWkuulsEbROkYziCL58JYrUxLB+W1ALj1mCc3jwcX2Tt5OY2Aag06ofg8pEoXEQV/a9+05qQAi5Sq8uT07Sw==", + "@effectionx/fetch@0.2.0_effection@4.1.0-alpha.7": { + "integrity": "sha512-0W15D9WuFUI6PEApaimxppacgk1WvJNxYwQ+P/tjWTzrPOUK8wrGlj6bqLrgfEaXqyOpdHbFI1eEz7wq1BDubw==", "dependencies": [ + "@effectionx/context-api", "effection" ] }, - "@effectionx/fs@0.2.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-aTT7Rbl8r0/0EgX+qT36gvfJnzAfjQ/+sROPhV2Ms4VcPONqwbunClWwX7B6m0jCHsER/gg4E45s60h6yatVFw==", + "@effectionx/fs@0.3.0_effection@4.1.0-alpha.7": { + "integrity": "sha512-I8RSIU80twN1WdeYRPD3utRD+niORiS08U0+LPNphwum94rwa/wHQNQUtNe19Bfbll+3GQxvJF+M95dYZSVxdQ==", "dependencies": [ + "@effectionx/context-api", "effection" ] }, - "@effectionx/middleware@0.1.0": { - "integrity": "sha512-xPpQIf1PQaox+H/e/yxZtop4kLxQkrEb8BUtmqcnmzVVbV8iJLNQeRzuSEAWQLAnVu8xa5SjGzLpb5UGYTLYgg==" + "@effectionx/middleware@0.1.1": { + "integrity": "sha512-ss/bZRkt/xzJNE59r8NR1+0K/xQcIyCm0y9n8FYC8jKdFn51SPe3m3t7EfPcK8zkdjCoTOU7k1UpIXRl26asYA==" }, - "@effectionx/node@0.2.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-bUwnCqzBsVERGzKZRTc6XMZ6yDLkRPgcxSvM6eAkuc2D5A7L0+nSu4J/x60y6geSYrAVv2UZBgAktukNtB6LxA==", + "@effectionx/node@0.2.4_effection@4.1.0-alpha.7": { + "integrity": "sha512-cPnp3fvfBKjGWekmBHdhZr5ScAr3Mg+x5IXpO8uKFe7AZ8EPAT9Di6skuB4kuGFJtRtS0Z1e5G4+2eJyapKhYA==", "dependencies": [ "effection" ] }, - "@effectionx/process@0.7.3_effection@4.1.0-alpha.7": { - "integrity": "sha512-ic+cv9aNeq0UgF+SO61jd8nYLiF3jFT2c6n+nOYstc4pmtUez70yFb0H5Rzppu21wql5QYCbQayVrRRUa5YRQQ==", + "@effectionx/process@0.8.1_effection@4.1.0-alpha.7": { + "integrity": "sha512-xyXlFja0Ill80lQ3IYfksXtJkqVmWuUOogRn/qlHWCAGlZj+MGGF8gOFbyzk/3Kx4pj14riVGgF/cyT5XCzqDw==", "dependencies": [ + "@effectionx/context-api", "@effectionx/node", + "@effectionx/scope-eval", "cross-spawn", "ctrlc-windows", "effection", "shellwords-ts" ] }, - "@effectionx/scope-eval@0.1.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-Jcy0vGdD3/8EGKf4FSICOKfJkjg3VnrxhM21pdum26du/odZ0ytX66/UcyvRW3b88E8HxsFPL1e6+7QRcJliDg==", + "@effectionx/scope-eval@0.1.3_effection@4.1.0-alpha.7": { + "integrity": "sha512-Acn45lb3H94WYhNVHXYtXOZYzjpBGDPPlsyW1Talb/vYjQzCzus5lkxxOlPyphzvi7d+7mGNXiIVt4JLSZmLnQ==", "dependencies": [ "effection" ] }, - "@effectionx/signals@0.5.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-ftWU0/+LTafPjFQ4mOfwIBHT75BtA2T44YJP7+nR/d8S2kURCzkR04a2NHVbk274XRfh354qpukBULDTchZlQw==", + "@effectionx/signals@0.5.4_effection@4.1.0-alpha.7": { + "integrity": "sha512-c3tnlq9qqjb4fb/4g+uf03ABbvaDbgcXqWZRuifXOFNeTyhnBy5t86Fpk0tVKBLQI2M9sStV0c62xxHXPhH2Pw==", "dependencies": [ "effection", "immutable" ] }, - "@effectionx/stream-helpers@0.8.1_effection@4.1.0-alpha.7": { - "integrity": "sha512-17rocf3av2VId8uqZJxBREhQRSaowA7+MKAbu27P3ZboIhpuIu8jqoQ1+YfKWdMy/ORrApeIljgoJl+1hJ3fvQ==", + "@effectionx/stream-helpers@0.8.3_effection@4.1.0-alpha.7": { + "integrity": "sha512-3yNSrdmW3ahOAXrEnBGmlzxp7k9Yzixtqzij98y167srYdAE8sm+V/WNtMLHYScShzw2hl6E8uCm9ghhQw7zKA==", "dependencies": [ "@effectionx/signals", "@effectionx/timebox", @@ -473,14 +485,14 @@ "remeda" ] }, - "@effectionx/test-adapter@0.7.3_effection@4.1.0-alpha.7": { - "integrity": "sha512-OgGzsIhBN8XYsFDAETbeGqwwrW2sNdQukxHRNNngjJE0G6LiKkwDrXs8ANGzarPihoE02YANVMbyWAruBuUnYg==", + "@effectionx/test-adapter@0.7.4_effection@4.1.0-alpha.7": { + "integrity": "sha512-zPA5dz2SKG1N/1WxIxYy4zBB1qjviLZy6o/u8PEQo82Tnjtch4rS+2zIrHriWGKX6KY+5VjPlryjtzcBaxvD3Q==", "dependencies": [ "effection" ] }, - "@effectionx/timebox@0.4.2_effection@4.1.0-alpha.7": { - "integrity": "sha512-CT1XCCXmYgxFjIJmz0kzBbDG0W1Jc/i8l4r2Hecu+gYXp22DW8bAkVPKYIDdR4acAC1flqevlWA8xWaNBUfb6w==", + "@effectionx/timebox@0.4.3_effection@4.1.0-alpha.7": { + "integrity": "sha512-cc7SLpL3svAYK8M5NS8kLQuL0lrZNoQb+Hi9NSaWOudzAW1HoewuDfUtfXLemPJnnLqLYhbghRhmpVqCm4Xg3Q==", "dependencies": [ "effection" ] @@ -2840,16 +2852,17 @@ "dependencies": [ "jsr:@std/testing@1", "npm:@durable-streams/client@~0.2.2", - "npm:@effectionx/converge@~0.1.3", - "npm:@effectionx/fetch@~0.1.2", - "npm:@effectionx/fs@0.2.2", - "npm:@effectionx/middleware@0.1.0", - "npm:@effectionx/node@~0.2.2", - "npm:@effectionx/process@~0.7.3", - "npm:@effectionx/scope-eval@~0.1.2", - "npm:@effectionx/stream-helpers@~0.8.1", - "npm:@effectionx/test-adapter@~0.7.3", - "npm:@effectionx/timebox@~0.4.2", + "npm:@effectionx/context-api@0.6.0", + "npm:@effectionx/converge@0.1.4", + "npm:@effectionx/fetch@0.2.0", + "npm:@effectionx/fs@0.3.0", + "npm:@effectionx/middleware@0.1.1", + "npm:@effectionx/node@0.2.4", + "npm:@effectionx/process@0.8.1", + "npm:@effectionx/scope-eval@0.1.3", + "npm:@effectionx/stream-helpers@0.8.3", + "npm:@effectionx/test-adapter@0.7.4", + "npm:@effectionx/timebox@0.4.3", "npm:@types/node@^24.5.2", "npm:configliere@~0.2.3", "npm:effection@4.1.0-alpha.7", @@ -2862,16 +2875,17 @@ "packageJson": { "dependencies": [ "npm:@durable-streams/client@~0.2.2", - "npm:@effectionx/converge@~0.1.3", - "npm:@effectionx/fetch@~0.1.2", - "npm:@effectionx/fs@0.2.2", - "npm:@effectionx/middleware@0.1.0", - "npm:@effectionx/node@~0.2.2", - "npm:@effectionx/process@~0.7.3", - "npm:@effectionx/scope-eval@~0.1.2", - "npm:@effectionx/stream-helpers@~0.8.1", - "npm:@effectionx/test-adapter@~0.7.3", - "npm:@effectionx/timebox@~0.4.2", + "npm:@effectionx/context-api@0.6.0", + "npm:@effectionx/converge@0.1.4", + "npm:@effectionx/fetch@0.2.0", + "npm:@effectionx/fs@0.3.0", + "npm:@effectionx/middleware@0.1.1", + "npm:@effectionx/node@0.2.4", + "npm:@effectionx/process@0.8.1", + "npm:@effectionx/scope-eval@0.1.3", + "npm:@effectionx/stream-helpers@0.8.3", + "npm:@effectionx/test-adapter@0.7.4", + "npm:@effectionx/timebox@0.4.3", "npm:@types/node@22", "npm:acorn@^8.16.0", "npm:effection@4.1.0-alpha.7", @@ -2906,6 +2920,7 @@ }, "core": { "dependencies": [ + "npm:@effectionx/context-api@0.6.0", "npm:acorn@^8.16.0", "npm:gray-matter@^4.0.3", "npm:magic-string@~0.30.21", @@ -2916,7 +2931,19 @@ "npm:remend@^1.2.2", "npm:unist-util-select@5", "npm:zod@^4.3.6" - ] + ], + "packageJson": { + "dependencies": [ + "npm:@effectionx/context-api@0.6.0" + ] + } + }, + "runtime": { + "packageJson": { + "dependencies": [ + "npm:@effectionx/context-api@0.6.0" + ] + } }, "site": { "dependencies": [ diff --git a/package.json b/package.json index a742f2b..8f079d2 100644 --- a/package.json +++ b/package.json @@ -25,16 +25,17 @@ "dependencies": { "@durable-streams/client": "^0.2.2", "effection": "4.1.0-alpha.7", - "@effectionx/converge": "^0.1.3", - "@effectionx/fetch": "^0.1.2", - "@effectionx/fs": "0.2.2", - "@effectionx/middleware": "0.1.0", - "@effectionx/node": "^0.2.2", - "@effectionx/process": "^0.7.3", - "@effectionx/scope-eval": "^0.1.2", - "@effectionx/stream-helpers": "^0.8.1", - "@effectionx/test-adapter": "^0.7.3", - "@effectionx/timebox": "^0.4.2", + "@effectionx/context-api": "0.6.0", + "@effectionx/converge": "0.1.4", + "@effectionx/fetch": "0.2.0", + "@effectionx/fs": "0.3.0", + "@effectionx/middleware": "0.1.1", + "@effectionx/node": "0.2.4", + "@effectionx/process": "0.8.1", + "@effectionx/scope-eval": "0.1.3", + "@effectionx/stream-helpers": "0.8.3", + "@effectionx/test-adapter": "0.7.4", + "@effectionx/timebox": "0.4.3", "acorn": "^8.16.0", "gray-matter": "^4.0.3", "magic-string": "^0.30.21", @@ -59,15 +60,14 @@ "test:node": "tsx --tsconfig tsconfig.node.json --test durable-streams/tests/*.test.ts core/tests/frontmatter.test.ts core/tests/heal.test.ts core/tests/scanner.test.ts core/tests/eval-transform.test.ts core/tests/eval-interpolate.test.ts core/tests/ema-api.test.ts core/tests/output-normalize.test.ts core/tests/output-terminal.test.ts", "test:bun": "bun test durable-streams/tests/ core/tests/frontmatter.test.ts core/tests/heal.test.ts core/tests/scanner.test.ts core/tests/eval-transform.test.ts core/tests/eval-interpolate.test.ts core/tests/ema-api.test.ts core/tests/output-normalize.test.ts core/tests/output-terminal.test.ts", "test:deno": "deno task test", - "lint": "oxlint -c .oxlintrc.json core/src/ cli/src/ durable-streams/ runtime/ && oxfmt --check core/src/ cli/src/ durable-streams/ runtime/ vendor/ test-support/", - "fmt": "oxfmt --write core/src/ cli/src/ durable-streams/ runtime/ vendor/ test-support/ core/tests/ durable-streams/tests/ packages/code-review-agent/" + "lint": "oxlint -c .oxlintrc.json core/src/ cli/src/ durable-streams/ runtime/ && oxfmt --check core/src/ cli/src/ durable-streams/ runtime/ test-support/", + "fmt": "oxfmt --write core/src/ cli/src/ durable-streams/ runtime/ test-support/ core/tests/ durable-streams/tests/ packages/code-review-agent/" }, "workspaces": [ "core", "cli", "durable-streams", "runtime", - "vendor/context-api", "packages/code-review-agent", "test-support", ".internal", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d5f98c..58d0a30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,36 +11,39 @@ importers: '@durable-streams/client': specifier: ^0.2.2 version: 0.2.2 + '@effectionx/context-api': + specifier: 0.6.0 + version: 0.6.0(effection@4.1.0-alpha.7) '@effectionx/converge': - specifier: ^0.1.3 - version: 0.1.3(effection@4.1.0-alpha.7) + specifier: 0.1.4 + version: 0.1.4(effection@4.1.0-alpha.7) '@effectionx/fetch': - specifier: ^0.1.2 - version: 0.1.2(effection@4.1.0-alpha.7) + specifier: 0.2.0 + version: 0.2.0(effection@4.1.0-alpha.7) '@effectionx/fs': - specifier: 0.2.2 - version: 0.2.2(effection@4.1.0-alpha.7) + specifier: 0.3.0 + version: 0.3.0(effection@4.1.0-alpha.7) '@effectionx/middleware': - specifier: 0.1.0 - version: 0.1.0 + specifier: 0.1.1 + version: 0.1.1 '@effectionx/node': - specifier: ^0.2.2 - version: 0.2.3(effection@4.1.0-alpha.7) + specifier: 0.2.4 + version: 0.2.4(effection@4.1.0-alpha.7) '@effectionx/process': - specifier: ^0.7.3 - version: 0.7.3(effection@4.1.0-alpha.7) + specifier: 0.8.1 + version: 0.8.1(effection@4.1.0-alpha.7) '@effectionx/scope-eval': - specifier: ^0.1.2 - version: 0.1.2(effection@4.1.0-alpha.7) + specifier: 0.1.3 + version: 0.1.3(effection@4.1.0-alpha.7) '@effectionx/stream-helpers': - specifier: ^0.8.1 - version: 0.8.1(effection@4.1.0-alpha.7) + specifier: 0.8.3 + version: 0.8.3(effection@4.1.0-alpha.7) '@effectionx/test-adapter': - specifier: ^0.7.3 - version: 0.7.3(effection@4.1.0-alpha.7) + specifier: 0.7.4 + version: 0.7.4(effection@4.1.0-alpha.7) '@effectionx/timebox': - specifier: ^0.4.2 - version: 0.4.2(effection@4.1.0-alpha.7) + specifier: 0.4.3 + version: 0.4.3(effection@4.1.0-alpha.7) acorn: specifier: ^8.16.0 version: 8.16.0 @@ -123,8 +126,8 @@ importers: core: dependencies: '@effectionx/context-api': - specifier: workspace:* - version: link:../vendor/context-api + specifier: 0.6.0 + version: 0.6.0(effection@4.1.0-alpha.7) '@executablemd/durable-streams': specifier: workspace:* version: link:../durable-streams @@ -139,8 +142,8 @@ importers: runtime: dependencies: '@effectionx/context-api': - specifier: workspace:* - version: link:../vendor/context-api + specifier: 0.6.0 + version: 0.6.0(effection@4.1.0-alpha.7) test-support: dependencies: @@ -148,8 +151,6 @@ importers: specifier: ^30.0.0 version: 30.3.0 - vendor/context-api: {} - packages: '@babel/code-frame@7.29.0': @@ -169,73 +170,61 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - '@effectionx/converge@0.1.3': - resolution: {integrity: sha512-LPuDslL53kA8etLgO/sMmqv9v66txOAO5d6DUWLnwZa6CwA2MTYkHEnZAoIGCnQYbjKTbPxlKatHgF15ihB4zA==} - engines: {node: '>= 22'} + '@effectionx/context-api@0.6.0': + resolution: {integrity: sha512-t004qvlkJDMB6EhHP1lOQ97PeIn90m7cv4+wsRPnx4YBem+pJzTL+Sm1KWbKMjMeFJz4oqllUWuBJZsCi+nuTw==} peerDependencies: effection: ^3 || ^4 - '@effectionx/fetch@0.1.2': - resolution: {integrity: sha512-CzoWkuulsEbROkYziCL58JYrUxLB+W1ALj1mCc3jwcX2Tt5OY2Aag06ofg8pEoXEQV/a9+05qQAi5Sq8uT07Sw==} - engines: {node: '>= 22'} + '@effectionx/converge@0.1.4': + resolution: {integrity: sha512-M11KU7jK3gOFGI4RT+Bf6ITMJntzzoGEO2KPx9r8uBoR+Rgwiyeuq+OeIHkuiHLUC+bB1g93KOj7aKR/G0F1/Q==} peerDependencies: effection: ^3 || ^4 - '@effectionx/fs@0.2.2': - resolution: {integrity: sha512-aTT7Rbl8r0/0EgX+qT36gvfJnzAfjQ/+sROPhV2Ms4VcPONqwbunClWwX7B6m0jCHsER/gg4E45s60h6yatVFw==} - engines: {node: '>= 22'} + '@effectionx/fetch@0.2.0': + resolution: {integrity: sha512-0W15D9WuFUI6PEApaimxppacgk1WvJNxYwQ+P/tjWTzrPOUK8wrGlj6bqLrgfEaXqyOpdHbFI1eEz7wq1BDubw==} peerDependencies: effection: ^3 || ^4 - '@effectionx/middleware@0.1.0': - resolution: {integrity: sha512-xPpQIf1PQaox+H/e/yxZtop4kLxQkrEb8BUtmqcnmzVVbV8iJLNQeRzuSEAWQLAnVu8xa5SjGzLpb5UGYTLYgg==} - engines: {node: '>= 22'} - - '@effectionx/node@0.2.2': - resolution: {integrity: sha512-bUwnCqzBsVERGzKZRTc6XMZ6yDLkRPgcxSvM6eAkuc2D5A7L0+nSu4J/x60y6geSYrAVv2UZBgAktukNtB6LxA==} - engines: {node: '>= 22'} + '@effectionx/fs@0.3.0': + resolution: {integrity: sha512-I8RSIU80twN1WdeYRPD3utRD+niORiS08U0+LPNphwum94rwa/wHQNQUtNe19Bfbll+3GQxvJF+M95dYZSVxdQ==} peerDependencies: effection: ^3 || ^4 - '@effectionx/node@0.2.3': - resolution: {integrity: sha512-M4hWrJYzRoYJyvdIk+J8uO2yLgw2Ywf9ddZygcdsiy4hvOxC1GpIrvKv/jYS0Ua71QagN46uEuPX7RlYVW3ueA==} - engines: {node: '>= 22'} + '@effectionx/middleware@0.1.1': + resolution: {integrity: sha512-ss/bZRkt/xzJNE59r8NR1+0K/xQcIyCm0y9n8FYC8jKdFn51SPe3m3t7EfPcK8zkdjCoTOU7k1UpIXRl26asYA==} + + '@effectionx/node@0.2.4': + resolution: {integrity: sha512-cPnp3fvfBKjGWekmBHdhZr5ScAr3Mg+x5IXpO8uKFe7AZ8EPAT9Di6skuB4kuGFJtRtS0Z1e5G4+2eJyapKhYA==} peerDependencies: effection: ^3 || ^4 - '@effectionx/process@0.7.3': - resolution: {integrity: sha512-ic+cv9aNeq0UgF+SO61jd8nYLiF3jFT2c6n+nOYstc4pmtUez70yFb0H5Rzppu21wql5QYCbQayVrRRUa5YRQQ==} - engines: {node: '>= 22'} + '@effectionx/process@0.8.1': + resolution: {integrity: sha512-xyXlFja0Ill80lQ3IYfksXtJkqVmWuUOogRn/qlHWCAGlZj+MGGF8gOFbyzk/3Kx4pj14riVGgF/cyT5XCzqDw==} peerDependencies: effection: ^3 || ^4 - '@effectionx/scope-eval@0.1.2': - resolution: {integrity: sha512-Jcy0vGdD3/8EGKf4FSICOKfJkjg3VnrxhM21pdum26du/odZ0ytX66/UcyvRW3b88E8HxsFPL1e6+7QRcJliDg==} - engines: {node: '>= 22'} + '@effectionx/scope-eval@0.1.3': + resolution: {integrity: sha512-Acn45lb3H94WYhNVHXYtXOZYzjpBGDPPlsyW1Talb/vYjQzCzus5lkxxOlPyphzvi7d+7mGNXiIVt4JLSZmLnQ==} peerDependencies: effection: ^3 || ^4 - '@effectionx/signals@0.5.2': - resolution: {integrity: sha512-ftWU0/+LTafPjFQ4mOfwIBHT75BtA2T44YJP7+nR/d8S2kURCzkR04a2NHVbk274XRfh354qpukBULDTchZlQw==} - engines: {node: '>= 22'} + '@effectionx/signals@0.5.4': + resolution: {integrity: sha512-c3tnlq9qqjb4fb/4g+uf03ABbvaDbgcXqWZRuifXOFNeTyhnBy5t86Fpk0tVKBLQI2M9sStV0c62xxHXPhH2Pw==} peerDependencies: effection: ^3 || ^4 - '@effectionx/stream-helpers@0.8.1': - resolution: {integrity: sha512-17rocf3av2VId8uqZJxBREhQRSaowA7+MKAbu27P3ZboIhpuIu8jqoQ1+YfKWdMy/ORrApeIljgoJl+1hJ3fvQ==} - engines: {node: '>= 22'} + '@effectionx/stream-helpers@0.8.3': + resolution: {integrity: sha512-3yNSrdmW3ahOAXrEnBGmlzxp7k9Yzixtqzij98y167srYdAE8sm+V/WNtMLHYScShzw2hl6E8uCm9ghhQw7zKA==} peerDependencies: effection: ^3 || ^4 - '@effectionx/test-adapter@0.7.3': - resolution: {integrity: sha512-OgGzsIhBN8XYsFDAETbeGqwwrW2sNdQukxHRNNngjJE0G6LiKkwDrXs8ANGzarPihoE02YANVMbyWAruBuUnYg==} - engines: {node: '>= 22'} + '@effectionx/test-adapter@0.7.4': + resolution: {integrity: sha512-zPA5dz2SKG1N/1WxIxYy4zBB1qjviLZy6o/u8PEQo82Tnjtch4rS+2zIrHriWGKX6KY+5VjPlryjtzcBaxvD3Q==} peerDependencies: effection: ^3 || ^4 - '@effectionx/timebox@0.4.2': - resolution: {integrity: sha512-CT1XCCXmYgxFjIJmz0kzBbDG0W1Jc/i8l4r2Hecu+gYXp22DW8bAkVPKYIDdR4acAC1flqevlWA8xWaNBUfb6w==} - engines: {node: '>= 22'} + '@effectionx/timebox@0.4.3': + resolution: {integrity: sha512-cc7SLpL3svAYK8M5NS8kLQuL0lrZNoQb+Hi9NSaWOudzAW1HoewuDfUtfXLemPJnnLqLYhbghRhmpVqCm4Xg3Q==} peerDependencies: effection: ^3 || ^4 @@ -1258,59 +1247,64 @@ snapshots: '@microsoft/fetch-event-source': 2.0.1 fastq: 1.20.1 - '@effectionx/converge@0.1.3(effection@4.1.0-alpha.7)': + '@effectionx/context-api@0.6.0(effection@4.1.0-alpha.7)': dependencies: - '@effectionx/timebox': 0.4.2(effection@4.1.0-alpha.7) + '@effectionx/middleware': 0.1.1 effection: 4.1.0-alpha.7 - '@effectionx/fetch@0.1.2(effection@4.1.0-alpha.7)': + '@effectionx/converge@0.1.4(effection@4.1.0-alpha.7)': dependencies: + '@effectionx/timebox': 0.4.3(effection@4.1.0-alpha.7) effection: 4.1.0-alpha.7 - '@effectionx/fs@0.2.2(effection@4.1.0-alpha.7)': + '@effectionx/fetch@0.2.0(effection@4.1.0-alpha.7)': dependencies: + '@effectionx/context-api': 0.6.0(effection@4.1.0-alpha.7) effection: 4.1.0-alpha.7 - '@effectionx/middleware@0.1.0': {} - - '@effectionx/node@0.2.2(effection@4.1.0-alpha.7)': + '@effectionx/fs@0.3.0(effection@4.1.0-alpha.7)': dependencies: + '@effectionx/context-api': 0.6.0(effection@4.1.0-alpha.7) effection: 4.1.0-alpha.7 - '@effectionx/node@0.2.3(effection@4.1.0-alpha.7)': + '@effectionx/middleware@0.1.1': {} + + '@effectionx/node@0.2.4(effection@4.1.0-alpha.7)': dependencies: effection: 4.1.0-alpha.7 - '@effectionx/process@0.7.3(effection@4.1.0-alpha.7)': + '@effectionx/process@0.8.1(effection@4.1.0-alpha.7)': dependencies: - '@effectionx/node': 0.2.2(effection@4.1.0-alpha.7) + '@effectionx/context-api': 0.6.0(effection@4.1.0-alpha.7) + '@effectionx/node': 0.2.4(effection@4.1.0-alpha.7) + '@effectionx/scope-eval': 0.1.3(effection@4.1.0-alpha.7) cross-spawn: 7.0.6 ctrlc-windows: 2.2.0 effection: 4.1.0-alpha.7 shellwords-ts: 3.0.1 - '@effectionx/scope-eval@0.1.2(effection@4.1.0-alpha.7)': + '@effectionx/scope-eval@0.1.3(effection@4.1.0-alpha.7)': dependencies: effection: 4.1.0-alpha.7 - '@effectionx/signals@0.5.2(effection@4.1.0-alpha.7)': + '@effectionx/signals@0.5.4(effection@4.1.0-alpha.7)': dependencies: effection: 4.1.0-alpha.7 immutable: 5.1.5 - '@effectionx/stream-helpers@0.8.1(effection@4.1.0-alpha.7)': + '@effectionx/stream-helpers@0.8.3(effection@4.1.0-alpha.7)': dependencies: - '@effectionx/signals': 0.5.2(effection@4.1.0-alpha.7) - '@effectionx/timebox': 0.4.2(effection@4.1.0-alpha.7) + '@effectionx/signals': 0.5.4(effection@4.1.0-alpha.7) + '@effectionx/timebox': 0.4.3(effection@4.1.0-alpha.7) effection: 4.1.0-alpha.7 immutable: 5.1.5 remeda: 2.33.6 - '@effectionx/test-adapter@0.7.3(effection@4.1.0-alpha.7)': + '@effectionx/test-adapter@0.7.4(effection@4.1.0-alpha.7)': dependencies: effection: 4.1.0-alpha.7 - '@effectionx/timebox@0.4.2(effection@4.1.0-alpha.7)': + '@effectionx/timebox@0.4.3(effection@4.1.0-alpha.7)': dependencies: effection: 4.1.0-alpha.7 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 362e55d..1c288aa 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,7 +3,6 @@ packages: - cli - durable-streams - runtime - - vendor/context-api - packages/code-review-agent - test-support - .internal diff --git a/runtime/package.json b/runtime/package.json index 487b406..1e7f24a 100644 --- a/runtime/package.json +++ b/runtime/package.json @@ -7,6 +7,6 @@ "./test": "./test/mod.ts" }, "dependencies": { - "@effectionx/context-api": "workspace:*" + "@effectionx/context-api": "0.6.0" } } diff --git a/tsconfig.node.json b/tsconfig.node.json index 88e7dd2..3e07701 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -17,7 +17,6 @@ "@executablemd/runtime/test": ["./runtime/test/mod.ts"], "@executablemd/durable-streams": ["./durable-streams/mod.ts"], "@executablemd/code-review-agent": ["./packages/code-review-agent/mod.ts"], - "@effectionx/context-api": ["./vendor/context-api/mod.ts"], "@effectionx/bdd/node": ["./test-support/bdd.ts"], "@effectionx/bdd/expect": ["./test-support/expect.ts"] } @@ -26,7 +25,6 @@ "core/**/*.ts", "durable-streams/**/*.ts", "runtime/**/*.ts", - "vendor/**/*.ts", "packages/**/*.ts", "test-support/**/*.ts" ], diff --git a/vendor/context-api/mod.ts b/vendor/context-api/mod.ts deleted file mode 100644 index 97be7eb..0000000 --- a/vendor/context-api/mod.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { type Middleware, combine } from "@effectionx/middleware"; -import { type Operation, createContext } from "effection"; - -export type { Middleware }; - -/** - * The shape of middlewares that can surround a particular {@link Api}. - * - * Members that are functions get middleware matching their signature. - * Members that are values get middleware wrapping a no-arg accessor. - */ -export type Around = { - [K in keyof A]: A[K] extends (...args: infer TArgs) => infer TReturn - ? Middleware - : Middleware<[], A[K]>; -}; - -export interface Api { - operations: Operations; - around: (around: Partial>, options?: { at: "min" | "max" }) => Operation; -} - -/** - * Maps each member of an API core to its lifted Operation form. - * - * - `Operation` -> pass-through as `Operation` - * - `(...args) => Operation` -> pass-through - * - `(...args) => T` (sync) -> lifted to `(...args) => Operation` - * - `T` (constant) -> lifted to `Operation` - * - * The `Operation` check comes first to prevent Operations - * (which have `[Symbol.iterator]`) from being misclassified as functions. - */ -export type Operations = { - [K in keyof A]: A[K] extends Operation - ? A[K] - : A[K] extends (...args: infer TArgs) => infer TReturn - ? TReturn extends Operation - ? A[K] - : (...args: TArgs) => Operation - : Operation; -}; - -/** - * Per-field middleware layers: two immutable arrays for priority ordering - * plus a pre-composed middleware function. - */ -type FieldMiddleware = { - max: Middleware[]; - min: Middleware[]; - composed: Middleware | undefined; -}; - -/** - * Maps each API field to its middleware layers. - */ -type MiddlewareRegistry = Record; - -export function createApi(name: string, handler: A): Api { - let fields = Object.keys(handler) as (keyof A)[]; - - let initial = fields.reduce((sum, field) => { - return Object.assign(sum, { - [field]: { - max: [], - min: [], - composed: undefined, - } satisfies FieldMiddleware, - }); - }, {} as MiddlewareRegistry); - - let context = createContext>(`$api:${name}`, initial); - - let operations = fields.reduce((api, field) => { - let handle = handler[field]; - if (typeof handle === "function") { - let fn = handle as (...args: any[]) => any; - return Object.assign(api, { - [field]: (...args: any[]) => ({ - *[Symbol.iterator]() { - let state = yield* context.expect(); - let { composed } = state[field as keyof A]; - let result = composed ? composed(args, fn) : fn(...args); - return isOperation(result) ? yield* result : result; - }, - }), - }); - } - return Object.assign(api, { - [field]: { - *[Symbol.iterator]() { - let state = yield* context.expect(); - let { composed } = state[field as keyof A]; - let result = composed ? composed([], () => handle) : handle; - return isOperation(result) ? yield* result : result; - }, - }, - }); - }, {} as Operations); - - function* around( - middlewares: Partial>, - options: { at: "min" | "max" } = { at: "max" }, - ): Operation { - let current = yield* context.expect(); - - let next = fields.reduce((sum, field) => { - let middleware = (middlewares as any)[field] as Middleware | undefined; - let fieldState = current[field as keyof A]; - - if (middleware) { - let max = [...fieldState.max]; - let min = [...fieldState.min]; - - if (options.at === "min") { - min = [middleware, ...min]; - } else { - max = [...max, middleware]; - } - - let composed = combine([...max, ...min]); - - return Object.assign(sum, { - [field]: { max, min, composed }, - }); - } - - return Object.assign(sum, { [field]: fieldState }); - }, {} as MiddlewareRegistry); - - yield* context.set(next); - } - - return { operations, around }; -} - -/** - * Check if a value is an Effection Operation at runtime. - * - * Excludes native iterables (strings, arrays, Maps, Sets) which have - * `[Symbol.iterator]` but are not Operations. - */ -function isOperation(target: Operation | T): target is Operation { - return ( - target != null && - !isNativeIterable(target) && - typeof (target as Operation)[Symbol.iterator] === "function" - ); -} - -function isNativeIterable(target: unknown): boolean { - return ( - typeof target === "string" || - Array.isArray(target) || - target instanceof Map || - target instanceof Set - ); -} diff --git a/vendor/context-api/package.json b/vendor/context-api/package.json deleted file mode 100644 index 8f5d9f9..0000000 --- a/vendor/context-api/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@effectionx/context-api", - "version": "0.5.0-vendored", - "type": "module", - "exports": "./mod.ts" -} From ed225c173a5ca8e3239df2421bacb7ecac8d1038 Mon Sep 17 00:00:00 2001 From: Taras Mankovski <74687+taras@users.noreply.github.com> Date: Wed, 15 Jul 2026 00:31:16 -0400 Subject: [PATCH 2/2] fix: adapt to @effectionx/process 0.8 stdio api and ensure-based teardown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two compatibility fixes that the dependency alignment requires: - run-document: @effectionx/process@0.8 introduces a Stdio api whose default middleware echoes child-process stdout/stderr to the terminal (0.7 captured silently). Document exec/daemon output is captured via .join() and the journal, so install suppressing Stdio middleware in the document pipeline — otherwise live runs print raw child output that replay runs don't, breaking byte-identical replay (CJ5/CJ6). - durable-streams: move async teardown out of try/finally into yield* ensure() in runDurableChild (Close-event emission) and the demo's test-server resource. Effection's teardown contract requires operation-driving teardown (yield*) to be registered via ensure(); a finally block cannot reliably drive operations during shutdown or cancellation. --- core/src/run-document.ts | 6 ++++ durable-streams/combinators.ts | 51 +++++++++++++++++---------------- durable-streams/demo/observe.ts | 9 ++---- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/core/src/run-document.ts b/core/src/run-document.ts index 74b1845..0ba5217 100644 --- a/core/src/run-document.ts +++ b/core/src/run-document.ts @@ -49,6 +49,7 @@ import { daemonFactory } from "./modifiers/daemon.ts"; import { EvalEnvCtx, EvalScopeCtx } from "./eval-env.ts"; import type { EvalEnv } from "./eval-env.ts"; import { useEvalScope } from "@effectionx/scope-eval"; +import { Stdio } from "@effectionx/process"; // Re-export gray-matter — we use it for YAML frontmatter extraction import matter from "gray-matter"; @@ -416,6 +417,11 @@ export function* runDocument(options: RunDocumentOptions): Operation( // parent combinator (race/all) will cancel this child as part of // normal structured concurrency teardown, just like the original // run. The Close(cancelled) event already exists in the journal, - // so we skip re-emitting it (the finally block checks for this). + // so we skip re-emitting it (the ensure teardown checks for this). // // INVARIANT: This branch is only reachable when a parent combinator // (durableRace or durableAll with a failed sibling) will cancel this @@ -91,16 +98,31 @@ function* runDurableChild( childCounter: 0, }); - // Track whether we completed normally or via error, so that - // the finally block can detect cancellation (the remaining case). let closeEvent: Close | undefined; + yield* ensure(function* () { + // closeEvent still undefined means the child was cancelled before the + // normal-return or catch path ran. + if (!closeEvent) { + closeEvent = { + type: "close", + coroutineId: childId, + result: { status: "cancelled" }, + }; + } + + // Don't re-emit a Close event if one already exists in the journal + // (e.g., a cancelled child being replayed via suspend()). + if (!replayIndex.hasClose(childId)) { + yield* stream.append(closeEvent!); + } + }); + try { // Run the child workflow. DurableEffects inside the child read // DurableCtx from the scope, so they'll use childId. const result: T = yield* childWorkflow(); - // Record Close(ok) — will be appended in finally closeEvent = { type: "close", coroutineId: childId, @@ -109,7 +131,6 @@ function* runDurableChild( return result; } catch (error) { - // Record Close(err) — will be appended in finally closeEvent = { type: "close", coroutineId: childId, @@ -120,24 +141,6 @@ function* runDurableChild( }; throw error; - } finally { - // If closeEvent is still undefined, the generator was cancelled - // (Effection called iterator.return(), skipping both the normal - // return path and the catch block). - if (!closeEvent) { - closeEvent = { - type: "close", - coroutineId: childId, - result: { status: "cancelled" }, - }; - } - - // Don't re-emit a Close event if one already exists in the journal - // (e.g., a cancelled child being replayed via suspend()). - if (!replayIndex.hasClose(childId)) { - // Append the Close event. - yield* stream.append(closeEvent!); - } } } diff --git a/durable-streams/demo/observe.ts b/durable-streams/demo/observe.ts index 9ed2c4b..0b7c59b 100644 --- a/durable-streams/demo/observe.ts +++ b/durable-streams/demo/observe.ts @@ -14,7 +14,7 @@ import { FetchError, stream as fetchStream } from "@durable-streams/client"; import { DurableStreamTestServer } from "@durable-streams/server"; -import { call, createChannel, each, main, resource, spawn } from "effection"; +import { call, createChannel, each, ensure, main, resource, spawn, until } from "effection"; import type { Operation, Stream } from "effection"; import process from "node:process"; import type { DurableEvent } from "../mod.ts"; @@ -53,11 +53,8 @@ function useDurableStreamTestServer(): Operation { return resource(function* (provide) { const server = new DurableStreamTestServer(); yield* call(() => server.start()); - try { - yield* provide(server); - } finally { - yield* call(() => server.stop()); - } + yield* ensure(() => until(server.stop())); + yield* provide(server); }); }