npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@llm-dev-ops/llm-marketplace-graphql-gateway

v1.1.1

Published

GraphQL API Gateway for LLM Marketplace

Readme

GraphQL API Gateway

Enterprise-grade GraphQL API Gateway for the LLM Marketplace platform. Provides a unified, type-safe API layer for accessing all marketplace services.

Features

  • Unified Schema - Single GraphQL endpoint for all services
  • Type Safety - Strict TypeScript implementation with comprehensive type definitions
  • Performance - DataLoader batching, Redis caching, query optimization
  • Security - JWT authentication, role-based authorization, rate limiting
  • Real-time - WebSocket subscriptions for live updates
  • Developer Experience - GraphQL Playground, introspection, comprehensive documentation

Architecture

Client Applications
        ↓
GraphQL API Gateway (Apollo Server 4)
├─ Schema Stitching
├─ Authentication Middleware
├─ DataLoaders (N+1 prevention)
├─ Redis Cache
└─ REST Data Sources
        ↓
Microservices
├─ Publishing Service (port 3001)
├─ Discovery Service (port 3002)
├─ Consumption Service (port 3003)
└─ Admin Service (port 3004)

Quick Start

Prerequisites

  • Node.js 18+
  • Redis 7+
  • Running microservices (Publishing, Discovery, Consumption, Admin)

Installation

# Install dependencies
npm install

# Copy environment variables
cp .env.example .env

# Edit .env with your configuration
nano .env

Development

# Start development server with hot reload
npm run dev

# GraphQL Playground will be available at:
# http://localhost:4000/graphql

Production

# Build TypeScript
npm run build

# Start production server
npm start

Docker

# Build and run with Docker Compose
docker-compose up -d

# View logs
docker-compose logs -f graphql-gateway

# Stop
docker-compose down

API Documentation

Endpoints

  • GraphQL Endpoint: POST /graphql
  • WebSocket Subscriptions: ws://localhost:4000/graphql
  • GraphQL Playground: GET /graphql (development only)

Authentication

Include JWT token in Authorization header:

Authorization: Bearer <your-jwt-token>

Example Queries

Search Services

query SearchServices {
  searchServices(
    query: "text generation"
    filter: {
      category: "AI"
      minRating: 4.0
    }
    pagination: {
      limit: 10
    }
  ) {
    services {
      id
      name
      description
      rating
      provider {
        name
        verified
      }
      pricing {
        model
        price
        currency
      }
    }
    total
    took
  }
}

Get Service Details

query GetService($id: ID!) {
  service(id: $id) {
    id
    name
    description
    version
    category
    tags
    provider {
      id
      name
      email
      verified
      rating
    }
    pricing {
      model
      price
      currency
      tiers {
        name
        requestsIncluded
        price
      }
    }
    endpoints {
      url
      method
      description
    }
    rating
    usageCount
    createdAt
    updatedAt
  }
}

Create Service

mutation CreateService($input: CreateServiceInput!) {
  createService(input: $input) {
    ... on Service {
      id
      name
      status
    }
    ... on ValidationError {
      message
      fields {
        field
        message
      }
    }
  }
}

Subscribe to Service Updates

subscription OnServiceUpdated($id: ID!) {
  serviceUpdated(id: $id) {
    id
    name
    status
    updatedAt
  }
}

Directives

@auth

Requires user authentication:

type Query {
  recommendations: [Service!]! @auth
}

@requireRole(role: Role!)

Requires specific user role:

type Mutation {
  approveService(id: ID!): ApprovalResult! @requireRole(role: ADMIN)
}

@rateLimit(limit: Int!, window: Int!)

Limits requests per time window:

type Query {
  searchServices(query: String!): SearchResult!
    @rateLimit(limit: 200, window: 60)
}

@cacheControl(maxAge: Int!, scope: CacheControlScope)

Sets cache TTL for responses:

type Query {
  categories: [Category!]! @cacheControl(maxAge: 3600)
}

Schema

The schema is organized by domain:

  • Common - Scalars, pagination, errors, directives
  • Publishing - Service management and publishing
  • Discovery - Search, recommendations, categories
  • Consumption - Usage tracking, quotas, billing
  • Admin - Analytics, audit logs, user management

Custom Scalars

  • DateTime - ISO 8601 date-time string
  • JSON - Arbitrary JSON value
  • URL - Valid HTTP/HTTPS URL
  • EmailAddress - Valid email format
  • PositiveInt - Integer > 0
  • NonNegativeInt - Integer >= 0
  • NonNegativeFloat - Float >= 0

Error Handling

Errors are returned as union types for explicit handling:

union ServiceResult = Service | ValidationError | NotFoundError | AuthorizationError

Client can handle different error types:

mutation CreateService($input: CreateServiceInput!) {
  createService(input: $input) {
    ... on Service {
      id
      name
    }
    ... on ValidationError {
      message
      fields {
        field
        message
      }
    }
    ... on NotFoundError {
      message
      resourceType
    }
  }
}

Performance

DataLoader Batching

All relationship fields use DataLoader for automatic batching:

// Instead of N+1 queries
services.forEach(service => {
  const provider = await getProvider(service.providerId);
});

// DataLoader batches into single query
const providers = await batchGetProviders(allProviderIds);

Redis Caching

Query responses are automatically cached based on @cacheControl directives:

type Query {
  categories: [Category!]! @cacheControl(maxAge: 3600)
}

Cache headers are set on responses:

X-Cache: HIT
X-Response-Time: 5ms

Query Complexity

Maximum query complexity is limited to prevent expensive queries:

const MAX_COMPLEXITY = 1000;

Queries exceeding the limit are rejected:

{
  "errors": [{
    "message": "Query is too complex: 1250. Maximum allowed: 1000",
    "extensions": {
      "code": "QUERY_TOO_COMPLEX"
    }
  }]
}

Query Depth

Maximum query depth is limited to prevent deeply nested queries:

const MAX_DEPTH = 10;

Security

Authentication

JWT-based authentication with role hierarchy:

  • USER - Regular user
  • PROVIDER - Service provider
  • ADMIN - Administrator
  • SUPER_ADMIN - Super administrator

Rate Limiting

Field-level rate limiting prevents abuse:

type Query {
  searchServices(query: String!): SearchResult!
    @rateLimit(limit: 200, window: 60)
}

Rate limit exceeded errors include retry information:

{
  "errors": [{
    "message": "Rate limit exceeded",
    "extensions": {
      "code": "RATE_LIMIT_EXCEEDED",
      "limit": 200,
      "window": 60,
      "retryAfter": 45
    }
  }]
}

CORS

Configure allowed origins in environment:

ALLOWED_ORIGINS=https://marketplace.example.com,https://admin.example.com

Monitoring

Metrics

Metrics are collected for every request:

{
  "type": "graphql_request",
  "operation": "SearchServices",
  "status": "success",
  "duration": 125,
  "requestId": "1234567890-abc",
  "userId": "user-123",
  "timestamp": "2025-01-19T10:30:00.000Z"
}

Slow Field Warnings

Fields taking > 100ms are logged:

{
  "type": "slow_field",
  "field": "Query.searchServices",
  "duration": 250,
  "requestId": "1234567890-abc"
}

Health Check

Health endpoint returns system status:

query {
  health {
    status
    version
    uptime
    timestamp
    services {
      name
      status
      responseTime
    }
  }
}

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch

Environment Variables

| Variable | Description | Default | |----------|-------------|---------| | PORT | Server port | 4000 | | NODE_ENV | Environment | development | | API_BASE_URL | Base URL for microservices | http://localhost:3000 | | REDIS_URL | Redis connection string | redis://localhost:6379 | | JWT_SECRET | JWT signing secret | required | | MAX_QUERY_COMPLEXITY | Maximum query complexity | 1000 | | MAX_QUERY_DEPTH | Maximum query depth | 10 |

Troubleshooting

Connection Refused

If you get connection errors:

  1. Ensure Redis is running: redis-cli ping
  2. Verify microservices are accessible
  3. Check API_BASE_URL in .env

Authentication Errors

If you get authentication errors:

  1. Verify JWT token is valid
  2. Check JWT_SECRET matches token issuer
  3. Ensure token hasn't expired

Performance Issues

If queries are slow:

  1. Check Redis cache is working
  2. Enable DataLoader batching
  3. Review query complexity
  4. Check slow field warnings in logs

Contributing

  1. Follow TypeScript best practices
  2. Add tests for new features
  3. Update documentation
  4. Run linter: npm run lint

License

Proprietary - LLM Marketplace Platform