Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (buro26-graphql-codegen-client) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
GraphQL Codegen Client
Generate a secure, high-performance client SDK for your GraphQL API using GraphQL Codegen. Features include per-user caching, rate limiting, error handling, and middleware support.
Getting started
npm i --save-dev buro26-graphql-codegen-client buro26-graphql-codegen-zod @graphql-codegen/cli @graphql-codegen/schema-ast @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node
Usage
Create a codegen.ts file in the root of your project with the following content:
import type {CodegenConfig} from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'http://localhost:1337/graphql',
documents: 'src/lib/strapi/queries/**/!(*.generated).{ts,tsx}',
debug: true,
overwrite: true,
verbose: true,
generates: {
// optional: generate schema types
'./schema.graphql': {
plugins: ['schema-ast']
},
'src/lib/my-api/generated/types.ts': {
plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
config: {
withHooks: false,
maybeValue: 'T | null',
avoidOptionals: false
}
},
'src/lib/my-api/generated/client-factory.ts': {
plugins: ['buro26-graphql-codegen-client'],
config: {
logger: true,
typesImportPath: '@/lib/strapi/generated/types',
schemaImportPath: '@/lib/strapi/generated/schema'
}
},
'src/lib/my-api/generated/schema.ts': {
plugins: ['buro26-graphql-codegen-zod'],
config: {
onlyWithValidation: false,
lazy: true,
zodTypesMap: {
DateTime: 'string',
JSON: 'string',
ID: 'string',
Int: 'number',
Float: 'number',
Long: 'number',
String: 'string',
Boolean: 'boolean',
I18NLocaleCode: 'string'
},
zodSchemasMap: {
DateTime: 'z.string()',
JSON: 'z.any()',
Long: 'z.coerce.number()',
I18NLocaleCode: 'z.string()'
}
}
}
}
}
export default config
Add a script to your package.json to run the codegen:
{
"scripts": {
"codegen": "graphql-codegen"
}
}
Run the codegen script:
npm run codegen
Create a client from the generated code:
import {createClient} from '@/lib/my-api/generated/client-factory'
export const client = createClient({
url: process.env.MY_API_URL!,
logging: true,
// Optional: Global error handling
onError: (error, operation) => {
console.error('GraphQL Error:', error.message)
// Send to error tracking service (Sentry, etc.)
},
// Optional: Rate limit handling
onRateLimitExceeded: (type, token) => {
console.warn('Rate limit exceeded:', type)
// Show user notification or implement backoff strategy
}
})
Make a request
Import the client and make a request:
import {client} from '@/lib/my-api/client'
const {data} = await client.query.adres.fetch({
authToken: ctx.session?.accessToken,
variables: {
filters: {
id: {
eq: id
}
}
}
})
Per-operation error handling
You can also handle errors for specific operations:
const {data} = await client.query.adres.fetch({
authToken: ctx.session?.accessToken,
variables: { filters: { id: { eq: id } } },
// Custom error handler for this specific operation
onError: (error) => {
console.log('Custom error handler:', error.message)
// This will be called in addition to the global onError callback
}
})
Use the schema
Import the schema and use it to validate data. This is useful for example for form validation, or usage with tRPC.
procedure
.input(
client.query.adres.schema()
)
.query(async ({input, ctx}) => {
const {data} = await client.query.adres.fetch({
authToken: ctx.session?.accessToken,
variables: input
})
return data?.adressen?.data[0] ?? null
})
Features
🔒 Security Features
- Per-user cache isolation: Each user's data is cached separately to prevent cross-user data leakage
- Rate limiting: Built-in rate limiting with configurable limits (100 requests/minute per user, 10k global)
- Token-based authentication: Secure token handling with proper isolation
- Request deduplication: Prevents duplicate requests while maintaining security
⚡ Performance Features
- Intelligent caching: 500ms minimum cache duration with automatic cleanup
- Request deduplication: Identical requests are deduplicated to reduce server load
- Cached requests don't count against rate limits: Better user experience
- Memory efficient: Per-user cache instances with automatic cleanup
🛠️ Developer Experience
- TypeScript support: Full type safety with generated types
- Error handling: Global and per-operation error callbacks
- Rate limit monitoring: Callbacks for rate limit events
- Middleware support: Custom middleware for request/response processing
- Logging: Built-in logging with configurable levels
📊 Monitoring & Observability
const client = createClient({
url: process.env.API_URL!,
logging: true,
// Monitor errors
onError: (error, operation) => {
// Send to error tracking service
analytics.track('graphql_error', {
message: error.message,
operation: operation.kind,
operationName: operation.context.operationName
})
},
// Monitor rate limits
onRateLimitExceeded: (type, token) => {
// Track rate limit events
analytics.track('rate_limit_exceeded', {
type,
userId: extractUserIdFromToken(token)
})
}
})
Configuration Options
Client Options
interface ClientOptions {
url: string // GraphQL endpoint URL
logging?: boolean // Enable/disable logging (default: false)
middlewares?: Middleware[] // Custom middleware functions
onError?: ClientErrorCallback // Global error handler
onRateLimitExceeded?: RateLimitExceededCallback // Rate limit handler
}
Rate Limiting Configuration
The client includes built-in rate limiting with the following defaults:
- Per-user limit: 100 requests per minute
- Global limit: 10,000 requests per minute
- Window: 60 seconds
Rate limits apply to both queries and mutations, but cached requests don't count against limits.
Cache Configuration
- Cache duration: 500ms minimum
- Per-user isolation: Each user has separate cache instances
- Automatic cleanup: Expired entries are automatically removed
- Memory efficient: Only caches requests with valid authentication tokens
Test and Deploy
Running tests
To run tests, run the following command:
bun test
Contributing
Wish to contribute to this project? Pull the project from the repository and create a merge request.
Authors and acknowledgment
Buro26 - https://buro26.digital
Special thanks to all contributors and the open-source community for their support and contributions.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Project status
The project is currently in active development. We are continuously working on adding new features and improving the existing ones. Check the issues section for the latest updates and planned features.
Feel free to reach out if you have any questions or suggestions!