Kubb Configuration
Kubb adalah OpenAPI code generator yang digunakan untuk mengenerate TypeScript types dan React Query hooks secara otomatis dari OpenAPI specification.
📋 Overview
🔧 Alur Kerja Kubb
📁 Generated Structure
gen/
├── hooks/ # React Query hooks
│ ├── AuthPenggunaHooks/
│ │ ├── useGetAuthPengguna.ts
│ │ └── index.ts
│ ├── KeuanganPengelolaanGudangIndukHooks/
│ │ ├── usePostKeuanganPengelolaanGudangIndukNonInventarisasi.ts
│ │ └── index.ts
│ └── index.ts # Barrel export
├── types/ # TypeScript types
│ ├── models/
│ │ ├── PengelolaanGudangIndukNonInventarisasi.ts
│ │ └── ...
│ ├── dto/
│ │ ├── PenggunaPostRequest.ts
│ │ └── ...
│ └── index.ts # Barrel export
└── index.ts # Main barrel export
⚙️ Konfigurasi Utama
Input Configuration
input: {
path: './sisappra.filtered.json'
}
Menggunakan file yang sudah difilter oleh filter-openapi.mjs untuk menghindari generate endpoint yang tidak diperlukan.
Output Configuration
output: {
path: './gen', // Output directory
format: 'prettier', // Auto-format generated code
lint: 'eslint', // Auto-lint generated code
defaultBanner: false, // Tidak tambahkan banner default
clean: true // Clean output directory sebelum generate
}
🔌 Plugin Configuration
1. OAS Plugin (pluginOas)
pluginOas({
validate: true, // Validasi OpenAPI specification
contentType: 'application/json', // Default content type
generators: [] // Custom generators (kosong)
})
Fungsi: Memproses dan memvalidasi OpenAPI specification sebelum generation.
2. TypeScript Plugin (pluginTs)
pluginTs({
output: { path: './types' }, // Output untuk types
group: { type: 'tag', name: '{Group}Types' }, // Group by API tags
transformers: [{ // Custom name transformers
type: 'name',
fn: (name) => name.replace('ApiV1', '')
}],
enumType: 'asConst', // Enums sebagai const assertions
dateType: 'date', // Date objects, bukan string
oasType: false // Tidak gunakan OAS-specific types
})
Fitur Utama:
- Strong Typing: Enums sebagai
as constuntuk better type safety - Date Handling: Otomatis generate sebagai
Dateobjects - Clean Naming: Hapus
ApiV1prefix dari nama types - Organized Structure: Group by API tags
3. React Query Plugin (pluginReactQuery)
pluginReactQuery({
output: { path: './hooks' }, // Output untuk hooks
group: { type: 'tag', name: '{Group}Hooks' }, // Group by API tags
client: '@/lib/axios/config', // Custom axios instance
suspense: false, // Disable suspense untuk performance
transformers: [{ // Custom name transformers
type: 'name',
fn: (name) => name.replace('ApiV1', '')
}]
})
Fitur Utama:
- React Query Integration: Generate hooks dengan proper React Query integration
- Custom Client: Menggunakan axios instance yang sudah dikonfigurasi
- Performance Optimized: Tanpa suspense untuk better UX
- Consistent Naming: Sama dengan types naming convention
🎯 Contoh Penggunaan Generated Code
Import Types
import type {
PengelolaanGudangIndukNonInventarisasi,
PengelolaanGudangIndukNonInventarisasiRequest
} from '@/gen/types';
// atau grouped import
import type {
KeuanganPengelolaanGudangIndukTypes
} from '@/gen/types/models';
Import Hooks
import {
usePostKeuanganPengelolaanGudangIndukNonInventarisasi,
usePutKeuanganPengelolaanGudangIndukVerifikasi
} from '@/gen/hooks';
// atau grouped import
import {
KeuanganPengelolaanGudangIndukHooks
} from '@/gen/hooks/KeuanganPengelolaanGudangIndukHooks';
Usage in Component
import React from 'react';
import { usePostKeuanganPengelolaanGudangIndukNonInventarisasi } from '@/gen/hooks';
import type { PengelolaanGudangIndukNonInventarisasiRequest } from '@/gen/types';
function CreateInventoryForm() {
const createMutation = usePostKeuanganPengelolaanGudangIndukNonInventarisasi();
const handleSubmit = async (data: PengelolaanGudangIndukNonInventarisasiRequest) => {
try {
const result = await createMutation.mutateAsync({ data });
console.log('Success:', result);
} catch (error) {
console.error('Error:', error);
}
};
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button type="submit" disabled={createMutation.isPending}>
{createMutation.isPending ? 'Saving...' : 'Save'}
</button>
</form>
);
}
🔄 Development Workflow
1. Update OpenAPI
# Run filter script untuk update OpenAPI spec
node scripts/filter-openapi.mjs
# Generate types dan hooks
npx kubb build --config kubb.config.ts
2. Environment Variables
# Override default OpenAPI URL
export SWAGGER_URL="https://custom-api.example.com/docs.json"
# Override filtered output path
export FILTERED_PATH="./custom-filtered.json"
3. Package Scripts
{
"scripts": {
"generate": "node scripts/filter-openapi.mjs && npx kubb build",
"generate:watch": "npx kubb build --watch",
"generate:clean": "rm -rf gen && npm run generate"
}
}
🎨 Customization
Menambah Custom Transformers
transformers: [
{
type: 'name',
fn: (name) => {
// Custom naming logic
return name
.replace('ApiV1', '')
.replace(/([A-Z])/g, ' $1')
.trim();
}
}
]
Menambah Custom Generators
pluginOas({
generators: [
{
name: 'custom-generator',
output: './custom-output',
build: (api) => {
// Custom generation logic
return `// Custom generated code`;
}
}
]
})
🔧 Configuration Options
Available Plugin Options
| Plugin | Option | Type | Default | Description |
|---|---|---|---|---|
pluginOas | validate | boolean | true | Validasi OpenAPI spec |
pluginTs | enumType | string | 'enum' | Type untuk enums |
pluginTs | dateType | string | 'string' | Type untuk dates |
pluginReactQuery | suspense | boolean | false | Enable suspense mode |
pluginReactQuery | client | string | - | Custom query client |
Group Options
group: {
type: 'tag', // Group by API tags
name: '{Group}Types', // Template untuk nama folder
output: './types' // Output directory
}
🚨 Best Practices
1. Consistent Tagging
Pastikan API endpoints dikelompokkan dengan tags yang konsisten di OpenAPI spec.
2. Proper Type Safety
Manfaatkan generated types untuk menghindari runtime errors.
3. Error Handling
Gunakan proper error handling dengan generated hooks.
4. Code Organization
Import hooks dan types dengan proper barrel exports.
5. Regeneration
Regenerate code setiap ada perubahan di OpenAPI spec.
🔍 Troubleshooting
Common Issues
Problem: Generated types tidak update
Solution: Jalankan filter-openapi.mjs dulu, kemudian kubb build
Problem: Missing dependencies
Solution: Pastikan @kubb/cli dan plugins terinstall
Problem: Import errors
Solution: Check barrel exports di gen/index.ts
Debug Commands
# Check generated files
ls -la gen/hooks/ gen/types/
# Validate OpenAPI spec
npx kubb validate --input sisappra.filtered.json
# Build with verbose output
npx kubb build --config kubb.config.ts --verbose