Skip to content

chore: improve api executor flow#345

Merged
rhamzeh merged 8 commits into
mainfrom
chore/improve-api-executor
Feb 27, 2026
Merged

chore: improve api executor flow#345
rhamzeh merged 8 commits into
mainfrom
chore/improve-api-executor

Conversation

@rhamzeh

@rhamzeh rhamzeh commented Feb 26, 2026

Copy link
Copy Markdown
Member

Description

What problem is being solved?

How is it being solved?

What changes are made to solve it?

References

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • New Features

    • Added support for making requests to custom API endpoints with integrated authentication, retries, telemetry, and error handling.
  • Documentation

    • Updated examples and guidance for the new endpoint-calling capabilities and header handling best practices.
  • Improvements

    • Enhanced header enforcement for JSON requests to ensure proper content type negotiation.

…quests

* apiExecutor now has a consistent interface regardless of where called
* apiExecutor now allows specifying types to help with typings and reduce casting
* apiExecutor + runApiExecutor now centralize all retry + auth + telemetry logic
* operationName is now required
* add streamingApiExecutor
Copilot AI review requested due to automatic review settings February 26, 2026 15:52
@rhamzeh
rhamzeh requested review from a team as code owners February 26, 2026 15:52
@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR refactors the OpenFgaClient's raw API call interface by replacing the internal apiExecutor method with two new public methods—executeApiRequest and executeStreamedApiRequest—along with a new RequestBuilder utility function for constructing validated API requests with path parameter substitution and header enforcement.

Changes

Cohort / File(s) Summary
API Method Refactoring
client.ts, common.ts
Introduces executeApiRequest<T> and executeStreamedApiRequest public methods replacing apiExecutor. Adds RequestBuilder utility function that validates path parameters, constructs URLs, enforces Accept and Content-Type headers, and assembles query parameters. Relocates and re-exports HttpMethod, RequestBuilderParams, and RequestBuilderOptions types from common.ts.
Documentation Updates
README.md, CHANGELOG.md
Updates examples and guidance to reference new executeApiRequest and executeStreamedApiRequest method names. Changes documentation links to reflect the updated API surface and adds operationName parameter usage in code examples.
Test Coverage
tests/apiExecutor.test.ts, tests/headers.test.ts
Migrates all test cases from apiExecutor to executeApiRequest with operationName parameters. Adds tests for header enforcement behavior (Content-Type and Accept headers are SDK-protected and cannot be overridden). Updates assertions to validate path parameter substitution, encoding, and validation error handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ewanharris
  • SoulPancake
  • jimmyjames
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'chore: improve api executor flow' is vague and generic, lacking specificity about what was actually changed. While it references 'api executor', it doesn't convey that this PR introduces new public API methods (executeApiRequest and executeStreamedApiRequest) or the significant refactoring that occurred. Consider using a more descriptive title such as 'refactor: rename apiExecutor to executeApiRequest and executeStreamedApiRequest' to better communicate the main changes to reviewers.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/improve-api-executor

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.

@codecov-commenter

codecov-commenter commented Feb 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.57143% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.51%. Comparing base (92ef2d2) to head (9aaeafd).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
client.ts 66.66% 2 Missing ⚠️
common.ts 93.10% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #345      +/-   ##
==========================================
- Coverage   90.00%   88.51%   -1.50%     
==========================================
  Files          25       25              
  Lines        1531     1271     -260     
  Branches      289      249      -40     
==========================================
- Hits         1378     1125     -253     
- Misses         95      101       +6     
+ Partials       58       45      -13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread common.ts Fixed
@dosubot

dosubot Bot commented Feb 26, 2026

Copy link
Copy Markdown

Documentation Updates

2 document(s) were updated by changes in this PR:

Custom HTTP Headers Support
View Changes
@@ -177,7 +177,7 @@
 
 ```javascript
 const response = await fgaClient.executeApiRequest({
-  operationName: 'CustomEndpoint',        // For telemetry/logging
+  operationName: 'CustomEndpoint',        // Required for telemetry/logging
   method: 'POST',
   path: '/stores/{store_id}/custom-endpoint',
   pathParams: { store_id: process.env.FGA_STORE_ID },
@@ -192,13 +192,17 @@
 });
 ```
 
-You can pass custom headers in the `options` parameter. These headers are merged with global configuration headers, with per-request headers taking precedence:
+You can pass custom headers in either the `request.headers` parameter or the `options.headers` parameter. Headers from both sources are merged, with `options.headers` taking precedence:
 
 ```javascript
 const response = await fgaClient.executeApiRequest({
+  operationName: 'GetAuthorizationModels',
   method: 'GET',
   path: '/stores/{store_id}/authorization-models',
   pathParams: { store_id: 'your-store-id' },
+  headers: {
+    'X-Request-Source': 'my-app',
+  }
 }, {
   headers: {
     'X-Request-ID': '123e4567-e89b-12d3-a456-426614174000',
StreamedListObjects Feature Overview
View Changes
@@ -89,12 +89,13 @@
 **Example:**
 ```javascript
 const response = await fgaClient.executeApiRequest({
-  operationName: 'CustomEndpoint',
+  operationName: 'CustomEndpoint',  // Required: operation name for telemetry
   method: 'POST',
   path: '/stores/{store_id}/custom-endpoint',
   pathParams: { store_id: process.env.FGA_STORE_ID },
   body: { /* request body */ },
   queryParams: { page_size: 20 },
+  headers: { 'X-Custom-Header': 'value' },  // Optional: custom headers
 });
 ```
 

How did I do? Any feedback?  Join Discord

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request refactors the internal API execution flow to improve code organization and consistency. The main changes include:

Purpose: The PR consolidates the request-building logic into a unified RequestBuilder function and renames the public API method from apiExecutor to executeApiRequest (with a new executeStreamedApiRequest for streaming endpoints).

Changes:

  • Introduced a centralized RequestBuilder function in common.ts that handles path parameter substitution, query parameters, headers, and enforces SDK-required headers (Accept and Content-Type)
  • Renamed apiExecutor to executeApiRequest and added executeStreamedApiRequest for streaming endpoints
  • Refactored all API methods in OpenFgaApiFp to use the new executeApiRequest internally, eliminating the old OpenFgaApiAxiosParamCreator pattern
  • Updated tests to reflect the new method names and verify proper header handling
  • Updated documentation in README.md and CHANGELOG.md

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
common.ts Added RequestBuilder function and related types (RequestBuilderParams, RequestBuilderOptions) to centralize request building logic
api.ts Refactored all API methods to use executeApiRequest internally; removed OpenFgaApiAxiosParamCreator; added public executeApiRequest and executeStreamedApiRequest methods
client.ts Renamed apiExecutor to executeApiRequest, added executeStreamedApiRequest, updated types and documentation
tests/apiExecutor.test.ts Updated test suite to use new method names and added operationName parameter to all calls
tests/headers.test.ts Updated test assertions to reflect that SDK now enforces both Content-Type and Accept headers
README.md Updated documentation examples to use executeApiRequest instead of apiExecutor
CHANGELOG.md Added entry for the new methods with documentation link

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CHANGELOG.md Outdated
Comment thread common.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
tests/headers.test.ts (1)

466-490: ⚠️ Potential issue | 🟡 Minor

Add an explicit Accept assertion in the protected-header test.

This test title claims both Content-Type and Accept are enforced, but only Content-Type is currently asserted.

Suggested fix
       const scope = nock(testConfig.apiUrl!)
         .post(`/stores/${testConfig.storeId}/check`)
         .reply(function() {
           const headers = this.req.headers;
 
           // SDK enforces Content-Type and Accept for JSON APIs
           expect(headers["content-type"]).toBe("application/json");
+          expect(headers["accept"]).toBe("application/json");
 
           // Custom headers are passed through
           expect(headers["x-custom"]).toBe("definitely-works");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/headers.test.ts` around lines 466 - 490, The test "SDK enforces
Content-Type and Accept regardless of baseOptions headers" currently asserts
only Content-Type; update the nock reply handler in that test (inside the it
block where fgaClient is created and scope is defined) to also assert that
headers["accept"] === "application/json" so the test explicitly verifies the SDK
enforces Accept for JSON APIs; locate the reply function that reads
this.req.headers and add the Accept assertion alongside the existing
Content-Type and x-custom assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Line 6: The documentation link in the CHANGELOG entry that mentions
executeApiRequest and executeStreamedApiRequest contains a broken fragment with
a double `##`; update the URL in that entry to use a single `#` (e.g., change
https://github.com/openfga/js-sdk##calling-other-endpoints to
https://github.com/openfga/js-sdk#calling-other-endpoints) so the anchor
resolves correctly.

In `@common.ts`:
- Around line 482-486: The current unresolved-parameter detection uses a regex
(requestPathTemplate.match(/\{([^}]+)\}/)) which triggers a CodeQL regex
complexity finding; replace it with a deterministic brace scan: use
requestPathTemplate.indexOf('{') to find the first opening brace and then
requestPathTemplate.indexOf('}', openIndex+1) to find the matching closing
brace, extract the parameter name via substring between those indexes, and if
both exist throw the same FgaValidationError(parameterName, `Path parameter
'${parameterName}' was not provided for path: ${request.path}`); update the
logic in the block that references requestPathTemplate and unresolvedMatch to
remove the regex and use this simple index-based extraction instead.

---

Outside diff comments:
In `@tests/headers.test.ts`:
- Around line 466-490: The test "SDK enforces Content-Type and Accept regardless
of baseOptions headers" currently asserts only Content-Type; update the nock
reply handler in that test (inside the it block where fgaClient is created and
scope is defined) to also assert that headers["accept"] === "application/json"
so the test explicitly verifies the SDK enforces Accept for JSON APIs; locate
the reply function that reads this.req.headers and add the Accept assertion
alongside the existing Content-Type and x-custom assertions.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92ef2d2 and baf429b.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • README.md
  • api.ts
  • client.ts
  • common.ts
  • tests/apiExecutor.test.ts
  • tests/headers.test.ts

Comment thread CHANGELOG.md Outdated
Comment thread common.ts Outdated
@rhamzeh
rhamzeh force-pushed the chore/improve-api-executor branch from 75331e7 to 9aaeafd Compare February 27, 2026 02:48
@rhamzeh rhamzeh mentioned this pull request Feb 27, 2026
4 tasks
@rhamzeh
rhamzeh added this pull request to the merge queue Feb 27, 2026
Merged via the queue into main with commit 0f1b6a9 Feb 27, 2026
27 checks passed
@rhamzeh
rhamzeh deleted the chore/improve-api-executor branch February 27, 2026 04:02
@SoulPancake SoulPancake linked an issue Apr 2, 2026 that may be closed by this pull request
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.

Add "streaming variant" of ApiExecutor

5 participants