Skip to content

feat(fetch): add fetchApi with middleware support#158

Merged
taras merged 8 commits intomainfrom
feat/fetch-api
Apr 15, 2026
Merged

feat(fetch): add fetchApi with middleware support#158
taras merged 8 commits intomainfrom
feat/fetch-api

Conversation

@taras
Copy link
Copy Markdown
Member

@taras taras commented Feb 16, 2026

Summary

Convert @effectionx/fetch to use Effection's createApi pattern, enabling middleware for logging, mocking, and instrumentation.

Changes

  • Add fetchApi export with around() method for middleware
  • Middleware intercepts at the request level (not the builder)
  • Add middleware tests for logging, mocking, and scope isolation

Usage

import { fetchApi, fetch } from "@effectionx/fetch";
import { run } from "effection";

// Add logging middleware
await run(function* () {
  yield* fetchApi.around({
    *request(args, next) {
      let [input] = args;
      console.log("Fetching:", input);
      return yield* next(...args);
    },
  });

  // All fetch calls in this scope now log
  let data = yield* fetch("/api/users").json();
});

Backward Compatibility

The fetch() function remains unchanged. Use fetchApi.around() to add middleware that intercepts all requests in the current scope and its children.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a middleware-capable fetch core by exporting fetchApi and routing internal fetches through it; exposes createMockResponse and FetchResponse for testing; updates README with Effection v4.1+ notes and examples; adds tests for middleware behaviors; bumps package versions and effection dependency references.

Changes

Cohort / File(s) Summary
Documentation
fetch/README.md
Added Effection v4.1+ compatibility note and new fetchApi middleware/API section with examples for around() logging, mocking, and scope-scoped cleanup.
Core Middleware Implementation
fetch/fetch.ts
Introduced FetchApiCore interface and exported fetchApi: Api<FetchApiCore> via createApi("fetch", ...); delegated request execution to fetchApi.operations.fetch(...) so middleware can intercept/short-circuit; added createMockResponse and mock response plumbing; exported FetchResponse type.
Tests
fetch/fetch.test.ts
Added middleware API test suite exercising fetchApi.around for logging, conditional mocking (short-circuit), and scope isolation via spawned child scopes; updated imports to use FetchResponse and fetchApi.
Package metadata / deps
fetch/package.json, package.json
Bumped fetch package to 0.2.0; tightened peerDependencies (effection to ^4.1.0-alpha.3); root devDependency and pnpm override updated to a specific Effection package URL.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant FetchFn as fetch()
    participant FetchApi as fetchApi.operations
    participant Middleware as Middleware (around)
    participant HTTP as HTTP Request

    Client->>FetchFn: fetch(url, init)
    FetchFn->>FetchApi: fetch(input, init, shouldExpect)
    FetchApi->>Middleware: invoke wrapped operation
    alt Middleware intercepts / short-circuits
        Middleware->>Middleware: log/mock/transform
        Middleware-->>FetchApi: return mockResponse
    else Middleware passes through
        Middleware->>HTTP: perform actual HTTP request
        HTTP-->>Middleware: response
        Middleware-->>FetchApi: return response
    end
    FetchApi-->>FetchFn: resolved response
    FetchFn-->>Client: return result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • cowboyd

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Policy Compliance ❌ Error PR adds three new public exports to fetch package but fails to bump version from 0.2.0 to 0.3.0 as required by Version Bump Policy. Update fetch/package.json to bump version from 0.2.0 to 0.3.0 per Version Bump Policy for new public exports.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: adding fetchApi with middleware support to the fetch module.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main
Description check ✅ Passed The PR description follows the template structure with both Motivation and Approach sections clearly defined. It includes a comprehensive summary of changes, usage examples, and backward compatibility notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/fetch-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Feb 16, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@effectionx/fetch@158

commit: 843acf3

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
fetch/package.json (2)

1-34: ⚠️ Potential issue | 🟡 Minor

Missing files field in package.json.

Per coding guidelines, package.json must include a files field containing dist, mod.ts, and source files. This field controls what gets published to npm.

📦 Proposed fix to add files field
   "engines": {
     "node": ">= 22"
   },
+  "files": [
+    "dist",
+    "mod.ts",
+    "fetch.ts"
+  ],
   "sideEffects": false
 }

3-3: ⚠️ Potential issue | 🟠 Major

Version bump required.

Source files have changed (fetch.ts, fetch.test.ts) with a breaking peerDependency change (narrowed from "effection": "^3 || ^4" to "effection": "^4.1.0-alpha.3"). Per the version-bump policy, this requires at least a major version bump.

🤖 Fix all issues with AI agents
In `@fetch/package.json`:
- Around line 14-16: The peerDependencies change to "effection":
"^4.1.0-alpha.3" removes Effection v3 support and is a breaking change; update
package.json's "version" to a breaking bump (e.g., major or appropriate pre-1.0
bump) to reflect this, update any CHANGELOG/release notes to document the
removed v3 compatibility and the new requirement ("effection":
"^4.1.0-alpha.3"), and ensure any CI/release metadata that relies on the
package.json "version" is updated accordingly.

In `@fetch/README.md`:
- Around line 197-218: The example references an undefined helper
createMockResponse; update the README by either adding a minimal inline factory
implementation for createMockResponse that returns a FetchResponse-compatible
object (implementing properties like ok/status/statusText/headers/url and
generator methods json/text/arrayBuffer/blob/formData and expect), or explicitly
state that users must supply their own mock response factory and show a short
pseudo-signature; place this next to the example and reference fetchApi.around,
fetch, and the FetchResponse type so readers know how to integrate the helper
with the shown fetch("/api/users").json() call.

Comment thread fetch/package.json
Comment thread fetch/README.md Outdated
Comment thread fetch/fetch.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@fetch/fetch.test.ts`:
- Line 21: Tests are manually constructing FetchResponse-like stubs for fetch
and fetchApi; replace those manual stubs with the shared test helper
createMockResponse to keep the surface consistent and reduce boilerplate—locate
usages in fetch.test.ts where FetchResponse-like objects are built (near imports
of FetchResponse, HttpError, fetch, fetchApi) and swap the handcrafted objects
with calls to createMockResponse(...), ensuring the same status, headers, body,
and json/text behaviors are passed so assertions continue to work.

In `@fetch/fetch.ts`:
- Around line 130-216: The exported variable fetchApi is typed as
Api<FetchApiCore> but FetchApiCore is currently not exported, causing a
declaration emit error; export the interface FetchApiCore (e.g., change
"interface FetchApiCore" to "export interface FetchApiCore") so the public type
referenced by fetchApi is exported, then re-run the TypeScript build to ensure
declarations emit correctly.

In `@fetch/README.md`:
- Around line 199-214: The README example incorrectly constructs the
FetchResponse interface (new FetchResponse(...)) which is not instantiable in
TypeScript; replace that construction with the exported helper
createMockResponse to produce a mock response. In the fetchApi.around middleware
example (the generator method fetch), return createMockResponse(...) with the
same body, status and headers instead of new FetchResponse(...) so the snippet
compiles; ensure you import createMockResponse from "@effectionx/fetch" at the
top of the example.

Comment thread fetch/fetch.test.ts Outdated
Comment thread fetch/fetch.ts Outdated
Comment thread fetch/README.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@fetch/README.md`:
- Line 183: Examples use run() at lines with await run(function* () { ... })
while earlier example uses main(); update the two middleware examples to use the
same Effection entry point by replacing await run(...) with await main(...)
(keep the generator function contents unchanged) so that the examples
consistently call main() instead of run(); ensure any necessary main import or
helper used earlier is referenced the same way in those examples.

Comment thread fetch/README.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fetch/fetch.ts`:
- Around line 194-216: Bump the package minor version to 0.3.0 to reflect the
new public exports (fetchApi, createMockResponse, FetchApiCore); update the
version field in this package's package.json (and any release metadata or
changelog entries if present) so the published package version is 0.3.0 and
ensure the new symbols (fetchApi, createMockResponse, FetchApiCore) are included
in the package's public exports/entry points.
- Around line 347-353: Extend createMockResponse to accept an optional options
object so callers can customize status, headers, and raw body (allowing
non-JSON/error responses) before wrapping with createFetchResponse; update the
signature (createMockResponse(data: unknown, opts?: { status?: number; headers?:
Record<string,string>; rawBody?: string; }) ), use opts.status defaulting to
200, merge opts.headers with a default Content-Type: application/json when
rawBody is not provided, stringify data only when not using rawBody and
Content-Type is JSON, and construct the Response accordingly before passing it
to createFetchResponse so tests can mock non-200 and custom-header responses.

Comment thread fetch/fetch.ts Outdated
Comment thread fetch/fetch.ts Outdated
Comment thread fetch/fetch.ts Outdated
Comment thread effect-ts/effect-runtime.ts Outdated
Comment thread fetch/api.ts Outdated
taras added 6 commits April 9, 2026 19:56
Extract FetchApi using @effectionx/context-api for middleware decoration.
Rename FetchApiCore to FetchHandler per review feedback. Keep
createFetchResponse internal. Add middleware tests for logging,
mocking, and scope isolation.
@taras taras requested a review from cowboyd April 10, 2026 00:09
@taras taras merged commit 093b9e2 into main Apr 15, 2026
6 checks passed
@taras taras deleted the feat/fetch-api branch April 15, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants