Skip to content

Conversation

productdevbook
Copy link
Owner

@productdevbook productdevbook commented Aug 21, 2025

Summary

This PR introduces multi-service GraphQL support with advanced schema download capabilities, allowing developers to connect to multiple external GraphQL APIs alongside their main GraphQL server.

🚀 Key Features

Multi-Service Architecture

  • Folder-based organization: Each service gets its own folder (default/, countries/, github/, etc.)
  • Main service in default folder: Your existing GraphQL server is now organized in default/ folder
  • Type isolation: Service-specific TypeScript types prevent import conflicts
  • Centralized exports: Clean import structure via #graphql/client
  • Automatic SDK generation: Type-safe GraphQL SDKs for each service

Advanced Schema Download & Caching

  • Flexible download modes: Choose behavior that fits your workflow
  • Offline development: Work without internet after initial schema download
  • Build performance: Avoid unnecessary network requests
  • Version control friendly: Commit schemas to track API changes

📋 Download Modes

Mode Behavior Use Case
'once' (recommended) Download only if file doesn't exist Offline-friendly development
'always' Check for updates on every build Always stay up-to-date
'manual' Never download automatically Full manual control
false Disable schema downloading Always use remote

🛠 Configuration Example

export default defineNuxtConfig({
  nitro: {
    graphql: {
      framework: 'graphql-yoga',
      externalServices: [
        {
          name: 'github',
          schema: 'https://docs.github.com/public/schema.docs.graphql',
          endpoint: 'https://api.github.com/graphql',
          downloadSchema: 'once', // Offline-friendly
          downloadPath: './schemas/github.graphql', // Optional custom path
          headers: () => ({ Authorization: `Bearer ${process.env.GITHUB_TOKEN}` }),
          documents: ['app/graphql/external/github/**/*.graphql']
        },
        {
          name: 'countries',
          schema: 'https://countries.trevorblades.com',
          endpoint: 'https://countries.trevorblades.com',
          downloadSchema: 'always', // Always check for updates
          documents: ['app/graphql/external/countries/**/*.graphql']
        }
      ]
    }
  }
})

📁 Generated File Structure

app/graphql/
├── index.ts                    # Centralized exports (NEW: includes all services)
├── default/                    # Main GraphQL service (NEW: moved from root)
│   ├── ofetch.ts              # HTTP client wrapper  
│   └── sdk.ts                 # Generated SDK
├── github/                     # GitHub GraphQL API (NEW)
│   ├── ofetch.ts              # GitHub-specific client
│   └── sdk.ts                 # GitHub SDK
└── countries/                  # Countries GraphQL API (NEW)
    ├── ofetch.ts              # Countries-specific client
    └── sdk.ts                 # Countries SDK

.nitro/graphql/schemas/         # Downloaded schemas (NEW)
├── github.graphql             # Cached GitHub schema
└── countries.graphql          # Cached countries schema

🛠️ GraphQL Config Setup (Recommended)

Update your graphql.config.ts for optimal IDE support:

For Multi-Service Setup:

// graphql.config.ts
import type { IGraphQLConfig } from 'graphql-config'

export default <IGraphQLConfig> {
  projects: {
    // Main GraphQL server (NEW: moved to default project)
    default: {
      schema: ['./.nuxt/graphql/schema.graphql'],
      documents: ['./app/graphql/default/**/*.{graphql,js,ts,jsx,tsx}']
    },
    // External services (NEW)
    github: {
      schema: [
        './.nuxt/graphql/schemas/github.graphql', // Downloaded schema
        'https://docs.github.com/public/schema.docs.graphql' // Remote fallback
      ],
      documents: ['./app/graphql/external/github/**/*.graphql']
    },
    countries: {
      schema: ['./.nuxt/graphql/schemas/countries.graphql'],
      documents: ['./app/graphql/external/countries/**/*.graphql']
    }
  }
}

Benefits:

  • 🎯 Service-specific validation and autocompletion
  • 🚀 IDE support for all GraphQL services
  • ✅ Real-time validation while typing
  • 🔍 Go-to definition across services

🔄 Migration Support

BREAKING CHANGE: Your main GraphQL service files are now organized in a default/ folder to support multi-service architecture.

Automatic detection and guidance for users upgrading from the old structure:

⚠️  OLD GRAPHQL STRUCTURE DETECTED!

📁 Found old files in app/graphql/ directory that need to be moved:
   • app/graphql/ofetch.ts
   • app/graphql/sdk.ts

🔄 Please manually move these files to the new structure:
   • app/graphql/ofetch.ts → app/graphql/default/ofetch.ts
   • app/graphql/sdk.ts → app/graphql/default/sdk.ts

📝 Also update your app/graphql/index.ts to include:
   export * from './default/ofetch'

💡 After moving, update your imports to use:
   import { $sdk } from "#graphql/client"

🚫 The old files will cause import conflicts until moved!

Migration Checklist:

  1. ✅ Move app/graphql/{ofetch,sdk}.ts to app/graphql/default/
  2. ✅ Update app/graphql/index.ts exports
  3. ✅ Update graphql.config.ts to use project-based configuration
  4. ✅ Verify imports still work: import { $sdk } from '#graphql/client'

Why this change?

  • Enables multi-service support without conflicts
  • Your main service remains fully functional in the default/ folder
  • Imports stay the same: import { $sdk } from '#graphql/client'
  • Cleaner organization for projects with multiple GraphQL endpoints

💡 Usage Examples

Type-safe Multi-Service Usage

// Import from different services
import type { GetRepositoryQuery } from '#graphql/client/github'
import type { GetCountriesQuery } from '#graphql/client/countries'  
import type { GetUsersQuery } from '#graphql/client' // Main service (from default/)

// Use service-specific clients
import { $githubSdk } from '~/app/graphql/github/ofetch'
import { $countriesSdk } from '~/app/graphql/countries/ofetch'
import { $sdk } from '#graphql/client' // Main service (from default/)

// Execute queries with full type safety
const repos = await $githubSdk.GetRepository({ owner: 'user', name: 'repo' })
const countries = await $countriesSdk.GetCountries()
const users = await $sdk.GetUsers() // Your existing GraphQL server

🎯 Benefits

  • 🔌 Multi-API Integration: Connect to GitHub, Shopify, or any GraphQL API
  • 📁 Clean Organization: Main service in default/, externals in named folders
  • ⚡ Performance: Optimized build times with smart caching
  • 🔒 Type Safety: Full TypeScript support for all services
  • 📱 Offline Support: Work without internet after schema download
  • 🎛 Flexible Configuration: Choose download behavior per service
  • 🛠️ IDE Integration: Full GraphQL Config support for all services
  • 🔄 Easy Migration: Smooth upgrade path with clear guidance

🧪 Testing

Tested with:

  • ✅ Standalone Nitro playground
  • ✅ Nuxt integration playground
  • ✅ Multiple external services (GitHub, Countries API)
  • ✅ All download modes ('once', 'always', 'manual', false)
  • ✅ TypeScript integration and path mappings
  • ✅ Migration scenarios from old structure
  • ✅ Default folder organization for main service
  • ✅ GraphQL Config integration with multi-project setup

📚 Documentation

  • Complete README updates with usage examples
  • TypeScript interface documentation
  • Migration guide for existing users with file movement instructions
  • Performance optimization explanations
  • Default folder organization explanation
  • GraphQL Config setup for IDE integration

• Add support for multiple external GraphQL services
• Implement folder-based organization (default/, serviceName/)
• Generate service-specific SDKs and type definitions
• Add validation for external service configurations
• Update Nuxt module to support TypeScript path mappings for external services
• Create centralized index.ts for automatic exports
• Migrate context.d.ts to context.ts with warning system
• Add @graphql-tools/url-loader for remote schema loading
…ADME

• Add multi-service support feature to main README features list
• Remove redundant external/README.md file
• Keep documentation centralized in main README
- Assign new URL() result to variable instead of using for side effects
- Add void operator to explicitly indicate validation-only usage
- Add flexible download modes: 'once', 'always', 'manual', boolean
- 'once' mode: Download only if file doesn't exist (offline-friendly)
- 'always' mode: Check for updates on every build (previous behavior)
- 'manual' mode: User manages schema files manually
- Rename schemaPath to downloadPath for clarity
- Store downloaded schemas in .nitro/graphql/schemas/ directory
- Improve build performance by avoiding unnecessary network requests
- Add comprehensive documentation with usage examples

This optimizes build performance while providing flexibility for different
development workflows and deployment scenarios.
@productdevbook productdevbook changed the title feat: Add multi-service GraphQL support with folder-based organization feat: Multi-Service GraphQL Support with Advanced Schema Download & Caching Aug 21, 2025
@productdevbook productdevbook changed the title feat: Multi-Service GraphQL Support with Advanced Schema Download & Caching feat: Multi-Service GraphQL Support with Default Folder Organization & Schema Caching Aug 21, 2025
@productdevbook productdevbook merged commit 293e07a into main Aug 21, 2025
1 check passed
@productdevbook productdevbook deleted the feat/multi-service-graphql-support branch August 21, 2025 13:50
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.

1 participant