Skip to content

Commit ba6c676

Browse files
feat: Add Apollo Federation subgraph support (#34)
* feat: Add Apollo Federation subgraph support - Add optional @apollo/subgraph integration with dynamic imports - Support both GraphQL Yoga and Apollo Server frameworks - Add federation helper functions (defineReference, defineEntity, defineSubgraph) - Enable federation: true in GraphQL Codegen when federation is active - Add federation playground for testing - Maintain backward compatibility with existing projects Closes #33 * refactor: Replace process.env with module-config virtual module - Replace process.env.NITRO_GRAPHQL_FEDERATION with typed virtual module - Add #nitro-internal-virtual/module-config for centralized config access - Remove environment variable dependencies in favor of build-time config - Enable access to all NitroGraphQLOptions through moduleConfig - Maintain type safety with proper TypeScript declarations This provides better developer experience and eliminates runtime env dependencies. * refactor: Remove Apollo Federation utility functions and related imports
1 parent 0e746fe commit ba6c676

28 files changed

+604
-1323
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
},
6868
"peerDependencies": {
6969
"@apollo/server": "^5.0.0",
70+
"@apollo/subgraph": "^2.0.0",
7071
"@apollo/utils.withrequired": "^3.0.0",
7172
"@as-integrations/h3": "^2.0.0",
7273
"graphql": "^16.11.0",
@@ -77,6 +78,9 @@
7778
"@apollo/server": {
7879
"optional": true
7980
},
81+
"@apollo/subgraph": {
82+
"optional": true
83+
},
8084
"@apollo/utils.withrequired": {
8185
"optional": true
8286
},
@@ -111,6 +115,7 @@
111115
},
112116
"devDependencies": {
113117
"@antfu/eslint-config": "catalog:",
118+
"@apollo/subgraph": "catalog:",
114119
"@nuxt/kit": "catalog:",
115120
"@nuxt/schema": "catalog:",
116121
"@types/node": "catalog:",

playground-federation/README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Apollo Federation Playground
2+
3+
This playground demonstrates how to create an Apollo Federation subgraph using Nitro GraphQL.
4+
5+
## Features
6+
7+
- **Federation Enabled**: Configured as a subgraph with Apollo Federation v2
8+
- **Entity Definitions**: User entity with `@key` directive for federation
9+
- **Reference Resolvers**: Implementation of `__resolveReference` for federated entities
10+
- **Schema-First Approach**: Using GraphQL schema files with federation directives
11+
12+
## Running the Playground
13+
14+
```bash
15+
# Install dependencies
16+
pnpm install
17+
18+
# Start Apollo Server federation subgraph
19+
pnpm dev:apollo
20+
21+
# Or start GraphQL Yoga federation subgraph
22+
pnpm dev:yoga
23+
```
24+
25+
The subgraph will be available at: http://localhost:3000/api/graphql
26+
27+
## Federation Configuration
28+
29+
### Apollo Server Federation
30+
31+
Configured in `nitro.config.apollo.ts`:
32+
33+
```ts
34+
export default defineNitroConfig({
35+
graphql: {
36+
framework: 'apollo-server',
37+
federation: {
38+
enabled: true,
39+
serviceName: 'users-service',
40+
serviceVersion: '1.0.0',
41+
serviceUrl: 'http://localhost:3000/api/graphql'
42+
}
43+
}
44+
})
45+
```
46+
47+
### GraphQL Yoga Federation
48+
49+
Configured in `nitro.config.yoga.ts`:
50+
51+
```ts
52+
export default defineNitroConfig({
53+
graphql: {
54+
framework: 'graphql-yoga',
55+
federation: {
56+
enabled: true,
57+
serviceName: 'users-service-yoga',
58+
serviceVersion: '1.0.0',
59+
serviceUrl: 'http://localhost:3000/api/graphql'
60+
}
61+
}
62+
})
63+
```
64+
65+
## Schema Structure
66+
67+
- **User Entity**: Defined with `@key(fields: "id")` for federation
68+
- **Federation Directives**: Uses `@external`, `@provides`, `@extends` directives
69+
- **Reference Resolvers**: Implements `__resolveReference` for User entity
70+
71+
## Testing Federation
72+
73+
You can test the subgraph introspection to verify federation support:
74+
75+
```graphql
76+
query {
77+
_service {
78+
sdl
79+
}
80+
}
81+
```
82+
83+
To use this subgraph in a federation gateway, include it in your gateway configuration with the service URL and schema.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { IGraphQLConfig } from 'graphql-config'
2+
3+
export default <IGraphQLConfig> {
4+
projects: {
5+
default: {
6+
schema: [
7+
'./.nitro/graphql/schema.graphql',
8+
],
9+
documents: [
10+
'./graphql/**/*.{graphql,js,ts,jsx,tsx}',
11+
],
12+
},
13+
},
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Example GraphQL config file please change it to your needs
2+
// import * as tables from '../drizzle/schema/index'
3+
// import { useDatabase } from '../utils/useDb'
4+
5+
export default defineGraphQLConfig({
6+
// graphql-yoga example config
7+
// context: () => {
8+
// return {
9+
// context: {
10+
// useDatabase,
11+
// tables,
12+
// },
13+
// }
14+
// },
15+
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Example context definition - please change it to your needs
2+
// import type { Database } from '../utils/useDb'
3+
4+
declare module 'h3' {
5+
interface H3EventContext {
6+
// Add your custom context properties here
7+
// useDatabase: () => Database
8+
// tables: typeof import('../drizzle/schema')
9+
// auth?: {
10+
// user?: {
11+
// id: string
12+
// role: 'admin' | 'user'
13+
// }
14+
// }
15+
}
16+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default defineSchema({
2+
3+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export default defineNitroConfig({
2+
modules: [
3+
'nitro-graphql',
4+
],
5+
graphql: {
6+
framework: 'apollo-server',
7+
federation: {
8+
enabled: true,
9+
serviceName: 'users-service',
10+
serviceVersion: '1.0.0',
11+
serviceUrl: 'http://localhost:3000/api/graphql',
12+
},
13+
},
14+
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default defineNitroConfig({
2+
srcDir: 'server',
3+
modules: [
4+
'nitro-graphql',
5+
],
6+
graphql: {
7+
framework: 'graphql-yoga',
8+
federation: {
9+
enabled: true,
10+
serviceName: 'users-service-yoga',
11+
serviceVersion: '1.0.0',
12+
serviceUrl: 'http://localhost:3000/api/graphql',
13+
},
14+
},
15+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export default defineNitroConfig({
2+
modules: [
3+
'nitro-graphql',
4+
],
5+
graphql: {
6+
framework: 'graphql-yoga',
7+
federation: {
8+
enabled: true,
9+
serviceName: 'users-service-yoga',
10+
serviceVersion: '1.0.0',
11+
serviceUrl: 'http://localhost:3000/api/graphql',
12+
},
13+
},
14+
})

playground-federation/package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "nitro-graphql-federation-playground",
3+
"type": "module",
4+
"private": true,
5+
"packageManager": "pnpm@10.15.0",
6+
"scripts": {
7+
"build": "nitro build",
8+
"build:apollo": "nitro build --config nitro.config.apollo.ts",
9+
"build:yoga": "nitro build --config nitro.config.yoga.ts",
10+
"dev": "nitro dev",
11+
"dev:apollo": "nitro dev --config nitro.config.apollo.ts",
12+
"dev:yoga": "nitro dev --config nitro.config.yoga.ts",
13+
"preview": "node .output/server/index.mjs"
14+
},
15+
"dependencies": {
16+
"@apollo/server": "catalog:",
17+
"@apollo/subgraph": "^2.11.2",
18+
"@as-integrations/h3": "catalog:",
19+
"graphql": "catalog:",
20+
"h3": "catalog:",
21+
"nitro-graphql": "link:../",
22+
"nitropack": "catalog:"
23+
}
24+
}

0 commit comments

Comments
 (0)