A type-safe GraphQL client for Hasura, optimized for Node.js and Nuxt environments with full TypeScript support.
- 🚀 ESM-first architecture
- 🎯 Full TypeScript support with generated types
- 📦 Auto-generated mutations and queries
- 🔄 Built-in GraphQL code generation
- 🛡️ Type-safe API calls
- ⚡ Optimized for Hasura
- 🌐 Universal runtime support (Node.js and Nuxt)
- 🔒 Built-in authentication handling
- 💪 Flexible query building
- 🎯 Direct GraphQL query support
- 🗄️ Built-in caching system
# Using pnpm (recommended)
pnpm add @incubrain/client
# Using npm
npm install @incubrain/client
# Using yarn
yarn add @incubrain/client
import { createClient } from "@incubrain/client";
const client = createClient({
endpoint: "YOUR_HASURA_ENDPOINT",
headers: {
"x-hasura-admin-secret": "YOUR_ADMIN_SECRET",
},
});
The client supports multiple ways to query your data:
// Using generated type-safe operations
const response = await client.FetchManyCompany({
limit: 10,
order_by: { created_at: 'desc' },
});
// Using the flexible query builder
const { companies } = await client.query('companies', {
limit: 10,
order_by: { scraped_at: 'desc_nulls_first' },
cols: ['id', 'name', 'scraped_at', 'url']
});
// With nested selections
const { users } = await client.query('users', {
limit: 5,
cols: {
id: true,
name: true,
profile: {
avatar_url: true,
bio: true
}
}
});
// Using raw GraphQL (great for quick prototyping)
const { companies } = await client.rawQuery(`
companies(limit: 10, order_by: {scraped_at: desc_nulls_first}) {
id
name
scraped_at
url
}
`);
You can import types directly from specific paths:
// Import table types
import { UserTable } from '@incubrain/client/tables';
// Import view types
import { UserProfileView } from '@incubrain/client/views';
// Import enums and constants
import { UserRoleEnum } from '@incubrain/client/constants';
// Import operation types
import { FetchUserProfileResult } from '@incubrain/client/operations';
The client includes built-in caching support:
const client = createClient({
endpoint: "YOUR_HASURA_ENDPOINT",
cache: true, // Enable caching
cacheTTL: 300, // Cache for 5 minutes
});
// Clear cache
await client.clearCache(); // Clear all cache
await client.clearCache('users:*'); // Clear user-related cache
interface ClientConfig {
endpoint: string; // GraphQL endpoint URL
headers?: Record<string, string>; // Custom headers
cache?: boolean; // Enable/disable caching
cacheTTL?: number; // Cache duration in seconds
logger?: Logger; // Custom logger
}
HASURA_ENDPOINT=https://your-hasura-endpoint/v1/graphql
HASURA_ADMIN_SECRET=your-admin-secret
// plugins/graphql.ts
import { createClient } from "@incubrain/client";
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const client = createClient({
endpoint: config.public.hasuraEndpoint,
headers: {
"x-hasura-admin-secret": config.hasuraAdminSecret,
},
cache: true
});
return {
provide: {
api: client,
},
};
});
<script setup lang="ts">
const { $api } = useNuxtApp();
// Using flexible query builder
const { users } = await $api.query('users', {
limit: 10,
cols: ['id', 'name', 'email']
});
// Using raw query
const { stats } = await $api.rawQuery(`
user_stats {
total_users
active_users
}
`);
// Using generated operations
const response = await $api.FetchUserProfile({
id: '123'
});
</script>
pnpm generate:operations
pnpm generate
pnpm build
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
- Enable splitting of the client into categories like admin | auth | client etc.
- This could be interesting if it was based on role, although the admin client would have everything then...
MIT