Skip to content

Conversation

@ashubham
Copy link

@ashubham ashubham commented Jul 24, 2025

Description

This PR allows subpath expoers from the server directory, to circumvent hard dependency on express. We could have removed express from server/index.ts but that would be a big breaking change for all the existing consumers.

Now someone could import internal exports:

import { A2ARequestHandler } from "@a2a-js/sdk/server/request_handler/a2a_request_handler.js";
import { JsonRpcTransportHandler } from "@a2a-js/sdk/server/transports/jsonrpc_transport_handler.js";

Fixes #55 #73

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @ashubham, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the package's modularity and usability by enabling consumers to import specific modules from subdirectories within the server-side exports. This change addresses a limitation in the previous export configuration, providing more granular access to the server-side components.

Highlights

  • Package Exports Configuration: I've updated the package.json to include a new wildcard export mapping (./server/*). This allows consumers of the package to directly import modules located in subdirectories of the dist/server output, supporting both ES Modules (.js) and CommonJS (.cjs) syntax.
  • TypeScript Type Resolution: To ensure proper type checking and IDE support, I've added a typesVersions entry. This configuration correctly resolves TypeScript types for the newly exposed server/* subdirectory exports, pointing to their corresponding declaration files within dist/server/*.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates package.json to allow sub-directory imports from the server module. The new wildcard export for server/* is missing a types condition, which will cause type resolution to fail for consumers using modern TypeScript configurations. A suggestion has been provided to add the necessary types condition.

@ydennisy
Copy link

@ashubham I think an update to the docs as part of this would be excellent!

Thanks for the PR!

@ajaynagotha
Copy link
Contributor

Hey @ashubham can i help you to update doc for this ?

@ashubham
Copy link
Author

Added an example in the Readme.

@ydennisy
Copy link

@swapydapy could we get this reviewed and merged?

I personally feel we should not have any coupling to the HTTP framework in this project at all.

@swapydapy swapydapy closed this in #71 Aug 3, 2025
swapydapy added a commit that referenced this pull request Aug 3, 2025
…ility (#71)

# fix: make Express dependency optional for edge environment
compatibility

## Summary

- Move A2AExpressApp to separate module at server/express/
- Remove A2AExpressApp from main server exports to avoid forcing Express
import
- Move express to peerDependencies and devDependencies
- Remove unused cors and body-parser dependencies entirely
- Add new package.json export for ./server/express
- Update import statements in samples and documentation
- Enables usage in Cloudflare Workers, Vercel Edge, and other non-Node
environments
- A2AExpressApp uses express.json() which is built into Express, making
body-parser unnecessary
- cors is not used by the library and is an application-level concern
developers should add themselves
- Only express remains as a peerDependency, accurately reflecting actual
requirements

Fixes #69 - Express dependency breaks edge environments

## Description

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make
sure it goes smoothly:

- [x] Follow the [`CONTRIBUTING`
Guide](https://github.com/google-a2a/a2a-js/blob/main/CONTRIBUTING.md).
- [x] Make your Pull Request title in the
<https://www.conventionalcommits.org/> specification.
- Important Prefixes for
[release-please](https://github.com/googleapis/release-please):
- `fix:` which represents bug fixes, and correlates to a
[SemVer](https://semver.org/) patch.
- `feat:` represents a new feature, and correlates to a SemVer minor.
- `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking
change (indicated by the `!`) and will result in a SemVer major.
- [x] Ensure the tests and linter pass
- [x] Appropriate docs were updated (if necessary)

Fixes #69 🦕

## Problem

The A2A SDK had a hard dependency on Express.js that prevented usage in
edge environments like Cloudflare Workers, Vercel Edge Runtime, and
other platforms that don't support Node.js core APIs.

**Issues identified:**
- 🚨 **Hard Express dependency** - `A2AExpressApp` was exported from main
server module, forcing Express import even when not used
- 📦 **Bloated installs** - Express and unused dependencies (cors,
body-parser) were required for all users
- 🚫 **Edge incompatibility** - Broke deployment to Cloudflare Workers,
Vercel Edge, and similar platforms
- ⚡ **Performance impact** - Unnecessary bundle size for non-Express
users
- 🗑️ **Unused dependencies** - cors and body-parser were listed but not
actually used by the library

## Solution

### 1. Modularized Express Integration
- ✅ Moved `A2AExpressApp` to separate `src/server/express/` module
- ✅ Removed Express exports from main `src/server/index.ts` 
- ✅ Created dedicated export path: `"./server/express"`

### 2. Cleaned Up Dependencies
```json
{
  "dependencies": {
    "uuid": "^11.1.0"
  },
  "peerDependencies": {
    "express": "^4.21.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.23",
    "express": "^4.21.2"
  }
}
```

**Key dependency decisions:**
- ✅ **express**: Required as peerDependency - actually used by
`A2AExpressApp`
- ❌ **body-parser**: Removed entirely - `A2AExpressApp` uses
`express.json()` instead
- ❌ **cors**: Removed entirely - not used by library, application-level
concern

### 3. Updated Package Exports
```json
{
  "./server/express": {
    "types": "./dist/server/express/index.d.ts",
    "import": "./dist/server/express/index.js",
    "require": "./dist/server/express/index.cjs"
  }
}
```

## Breaking Changes & Migration

### Before (❌ Problematic)
```typescript
import { A2AExpressApp } from "@a2a-js/sdk/server"; // Forces Express dependency
```

### After (✅ Clean)
```typescript
// Core server functionality (no Express dependency)
import { DefaultRequestHandler, AgentExecutor } from "@a2a-js/sdk/server";

// Express integration (optional, only when needed) 
import { A2AExpressApp } from "@a2a-js/sdk/server/express";
```

**For Express users, install peer dependency:**
```bash
npm install express
```

**For users who need CORS support, add it to your Express app:**
```bash
npm install cors
```

```typescript
import express from 'express';
import cors from 'cors';
import { A2AExpressApp } from "@a2a-js/sdk/server/express";

const app = express();
app.use(cors()); // Add CORS at application level
// ... rest of your Express setup
```

## Benefits

| Benefit | Before | After |
|---------|--------|-------|
| **Edge compatibility** | ❌ Broken | ✅ Works |
| **Bundle size** | ~2MB+ Express deps | Minimal core |
| **Install size** | All deps required | Express optional |
| **Developer experience** | Forced dependency | Explicit choice |
| **Dependency accuracy** | Unused deps included | Only required deps |

## Dependency Analysis

### Why body-parser was removed:
- `A2AExpressApp` uses `express.json()` which is built into Express
4.16+
- No import statements found for `body-parser` in the codebase
- Listing it as a peerDependency forced unnecessary installations

### Why cors was removed:
- No import statements found for `cors` in the codebase  
- CORS is an application-level concern that developers should configure
themselves
- Different applications have different CORS requirements
- Keeping it as a dependency misrepresented the library's actual
requirements

## Testing

- ✅ **All existing tests pass** (15/15)
- ✅ **Build succeeds** with new modular structure
- ✅ **Backward compatibility** maintained for core functionality
- ✅ **Express functionality** preserved when imported from new path

## Files Changed

- **`package.json`** - Updated exports and cleaned up dependency
structure
- **`src/server/index.ts`** - Removed `A2AExpressApp` export
- **`src/server/express/`** - New modular Express integration
- **`README.md`** - Updated import examples
- **`src/samples/agents/movie-agent/index.ts`** - Updated to use new
import paths

## Impact

This change enables the A2A SDK to be used in:
- ✅ Cloudflare Workers
- ✅ Vercel Edge Runtime  
- ✅ Deno Deploy
- ✅ Any edge/serverless environment
- ✅ Traditional Node.js servers (unchanged experience)

The dependency cleanup also:
- 🎯 **Accurately represents requirements** - only lists dependencies
actually used
- 💰 **Reduces install overhead** - consumers don't install unused
packages
- 🔧 **Improves flexibility** - developers choose their own CORS
configuration

---

**Type:** Bug fix  
**Breaking Change:** Minimal (import path only)  
**SemVer:** Patch

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: swapydapy <[email protected]>
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.

[Bug]: Hard dependency on Express library

3 participants