@kodeme-io/next-core-odoo-types
v0.8.4
Published
TypeScript type definitions for Odoo models - Use @kodeme-io/next-core-codegen to generate from your Odoo instance
Maintainers
Readme
@kodeme-io/next-core-odoo-types
TypeScript type definitions for Odoo ERP models - Ensuring type safety and data integrity across your Next-Core applications.
🎯 Purpose
This package solves the critical problem of type mismatches between mock data and real Odoo data by providing:
- Single Source of Truth: Types generated directly from Odoo schema
- Type Safety: Compile-time errors if mock data doesn't match Odoo
- Runtime Validation: Zod schemas for runtime data validation
- Auto-Generated: Types stay in sync with Odoo models
- Well-Documented: Complete field documentation and helpers
📦 Installation
pnpm add @kodeme-io/next-core-odoo-types🚀 Quick Start
Usage Patterns
✅ Recommended: Type-Only Imports (Components)
// For React components that only need types
import type {
ResPartner,
SaleOrder,
SfaVisit,
} from '@kodeme-io/next-core-odoo-types'
// Use in your code - 0KB runtime overhead!
const customer: ResPartner = {
id: 1,
name: 'ABC Corporation',
email: '[email protected]',
is_company: true,
customer_rank: 1,
// ... TypeScript enforces correct structure!
}✅ Recommended: Combined Imports (Services)
// For services that need both types and API
import { OdooAdapter } from '@kodeme-io/next-core-odoo-api'
import type { ResPartner } from '@kodeme-io/next-core-odoo-types'
const adapter = new OdooAdapter({...})
const customers = await adapter.searchRead<ResPartner>('res.partner')⚠️ Avoid: Importing Everything
// ❌ Don't do this - pulls in unused code
import * as OdooTypes from '@kodeme-io/next-core-odoo-types'Runtime Validation
import {
ResPartnerSchema,
validateOdooData,
} from '@kodeme-io/next-core-odoo-types'
// Validate data from API
const rawData = await fetch('/api/customers/1').then(r => r.json())
const customer = validateOdooData(ResPartnerSchema, rawData)
// ✅ Throws if data doesn't match schemaUse in Mock Generators
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
export function generateVisits(count: number): SfaVisit[] {
return Array.from({ length: count }, (_, i) => ({
id: i + 1,
name: `VIS${String(i + 1).padStart(4, '0')}`,
customer_id: [faker.number.int(), faker.company.name()],
user_id: [1, 'John Doe'],
scheduled_date: new Date().toISOString(),
state: faker.helpers.arrayElement(['draft', 'scheduled', 'done', 'cancelled']),
// ✅ TypeScript error if we use invalid state!
visit_type: 'sales_visit',
duration: 1,
company_id: [1, 'My Company'],
active: true,
}))
}📚 Available Types
Common Types
import type {
Many2One,
One2Many,
Many2Many,
Selection,
OdooDate,
OdooDateTime,
Monetary,
} from '@kodeme-io/next-core-odoo-types'Many2One: [id, display_name] or false
customer_id: [123, "ABC Corporation"]
customer_id: false // No relationOne2Many / Many2Many: Array of IDs
order_line: [1, 2, 3, 4]Selection: String literal union
state: 'draft' | 'confirmed' | 'done'Base Models
res.partner (Contact/Customer)
import type { ResPartner } from '@kodeme-io/next-core-odoo-types'
interface ResPartner {
id: number
name: string
email?: string | false
phone?: string | false
is_company: boolean
customer_rank: number
partner_latitude?: number
partner_longitude?: number
// ... 40+ more fields
}sale.order (Sales Order)
import type { SaleOrder, SaleOrderLine } from '@kodeme-io/next-core-odoo-types'
interface SaleOrder {
id: number
name: string // SO001
partner_id: Many2One<'res.partner'>
date_order: OdooDateTime
state: 'draft' | 'sent' | 'sale' | 'done' | 'cancel'
order_line: One2Many // sale.order.line IDs
amount_total: Monetary
// ... 60+ more fields
}sfa.visit (Field Visit)
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
interface SfaVisit {
id: number
name: string // VIS001
customer_id: Many2One<'res.partner'>
user_id: Many2One<'res.users'>
scheduled_date: OdooDateTime
state: 'draft' | 'scheduled' | 'done' | 'cancelled'
check_in_latitude?: number
check_in_longitude?: number
// ... 40+ more fields
}🛠️ Validation Schemas
Every type has a corresponding Zod schema:
import {
ResPartnerSchema,
SaleOrderSchema,
SfaVisitSchema,
} from '@kodeme-io/next-core-odoo-types'
// Validate data
const customer = ResPartnerSchema.parse(rawData)
// Safe validation (returns result object)
const result = ResPartnerSchema.safeParse(rawData)
if (result.success) {
console.log('Valid:', result.data)
} else {
console.error('Invalid:', result.error)
}🎨 Field Metadata
For building dynamic UIs (forms, tables):
import { SfaVisitFields } from '@kodeme-io/next-core-odoo-types'
SfaVisitFields.customer_id
// {
// name: 'customer_id',
// type: 'many2one',
// label: 'Customer',
// required: true
// }Use with FormBuilder:
import { FormBuilder } from '@kodeme-io/next-core-forms'
import { SfaVisitFields } from '@kodeme-io/next-core-odoo-types'
<FormBuilder
fields={[
SfaVisitFields.customer_id,
SfaVisitFields.scheduled_date,
SfaVisitFields.purpose,
]}
onSubmit={handleSubmit}
/>🔄 Type Generation Workflow
Current State (v0.8.0)
This package currently contains hand-crafted TypeScript types for common Odoo models. These provide a good starting point and serve as templates.
Future: Auto-Generation with Codegen
In future versions, use @kodeme-io/next-core-codegen to auto-generate types from YOUR Odoo instance:
┌─────────────────────────────────────────┐
│ 1. YOUR Odoo ERP Instance │
│ - Your custom models │
│ - Your custom fields │
│ - Your specific configuration │
└─────────────────────────────────────────┘
↓
[Introspect via fields_get API]
↓
┌─────────────────────────────────────────┐
│ 2. @kodeme-io/next-core-codegen │
│ CLI TOOL (the generator) │
│ - Connects to your Odoo │
│ - Introspects model schemas │
│ - Generates TypeScript code │
└─────────────────────────────────────────┘
↓
[Generates types into your project]
↓
┌─────────────────────────────────────────┐
│ 3. Your Project's src/types/odoo.ts │
│ GENERATED OUTPUT │
│ - TypeScript interfaces │
│ - Zod validation schemas │
│ - Field metadata │
└─────────────────────────────────────────┘
↓
[Import in your components]
↓
┌─────────────────────────────────────────┐
│ 4. Your Next.js App │
│ import type { ResPartner } │
│ from '@/types/odoo' │
│ - Type-safe data access │
│ - Compile-time validation │
└─────────────────────────────────────────┘Why Separate Packages?
Our architecture separates runtime behavior from compile-time safety for optimal performance:
| Package | Purpose | Bundle Size | When to Use | |---------|---------|-------------|-------------| | @kodeme-io/next-core-odoo-api | Runtime JSON-RPC client | 112K | Services, API calls, data fetching | | @kodeme-io/next-core-odoo-types | TypeScript types & validation | 220K | Components, type safety, validation | | @kodeme-io/next-core-codegen | Generator tool (CLI) | - | Generate types from your Odoo |
Benefits of Separation:
- ✅ Tree-shaking: Components import only types (0KB runtime)
- ✅ Independent versioning: Types can evolve faster than API
- ✅ Clear boundaries: Runtime vs compile-time concerns
- ✅ Better testing: Test types without network code
| Package | Purpose | You Should... | |---------|---------|---------------| | @kodeme-io/next-core-codegen | Generator tool (CLI) | Install as devDependency and run to generate types | | @kodeme-io/next-core-odoo-types | Template/reference types | Use as reference or starting point for your types |
Example Workflow:
# 1. Install the generator tool
pnpm add -D @kodeme-io/next-core-codegen
# 2. Generate types from YOUR Odoo instance
npx next-core-codegen generate-types \
--odoo-url=https://your-odoo.com \
--database=your-database \
--output=src/types/odoo.ts
# 3. Use the generated types in your app
import type { ResPartner } from '@/types/odoo'📖 Model Registry
import {
OdooModelRegistry,
ModelType,
ModelName,
isModelName,
getModelSchema,
validateModelRecord,
} from '@kodeme-io/next-core-odoo-types'
// Type-safe model access
type Customer = ModelType<'res.partner'> // = ResPartner
// Check if valid model name
if (isModelName('res.partner')) {
const schema = getModelSchema('res.partner')
}
// Validate record
const customer = validateModelRecord('res.partner', rawData)🎯 Benefits
Before (Manual Types)
// ❌ Manual type definition (might not match Odoo)
type Visit = {
state: 'pending' | 'done' | 'cancelled' // Wrong! Odoo has 'scheduled'
}
// ❌ No validation
const visit = mockData as Visit // Type cast, no checks
// ❌ Mock drifts from Odoo
// Mock has 'pending', Odoo has 'scheduled' → Runtime errors!After (Generated Types)
// ✅ Type generated from Odoo
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
// ✅ Compile-time validation
const visit: SfaVisit = {
state: 'pending' // ❌ TypeScript error! Invalid state
}
// ✅ Runtime validation
const visit = validateOdooData(SfaVisitSchema, rawData)
// ✅ Mock guaranteed to match Odoo
// Both use same type definition from this package🔧 Utilities
Helper Functions
import {
calculateVisitDuration,
isVisitCompleted,
getVisitStatusColor,
} from '@kodeme-io/next-core-odoo-types'
const visit: SfaVisit = { /* ... */ }
const duration = calculateVisitDuration(visit)
// Returns: number | null (hours)
const isCompleted = isVisitCompleted(visit)
// Returns: boolean
const color = getVisitStatusColor(visit)
// Returns: 'gray' | 'blue' | 'green' | 'red'Type Utilities
import type {
PartialRecord,
OmitMetadata,
WritableFields,
} from '@kodeme-io/next-core-odoo-types'
// Partial update (all fields optional)
type UpdateVisit = PartialRecord<SfaVisit>
// Without metadata fields
type CleanVisit = OmitMetadata<SfaVisit>
// Only writable fields
type CreateVisit = WritableFields<SfaVisit>📝 Required Odoo Modules
Different models require different Odoo modules:
| Model | Required Module | Description |
|-------|----------------|-------------|
| res.partner | Base (built-in) | Contacts/Customers |
| sale.order | sale | Sales Management |
| crm.lead | crm | CRM/Leads |
| sfa.visit | sfa_management | Custom SFA module |
| sfa.target | sfa_management | Custom SFA module |
| hr.employee | hr | HR Management |
| hr.attendance | hr_attendance | Attendance Tracking |
Note: Install required modules in your Odoo instance before generating types.
🚀 Type Generation
Recommended: Use Codegen Package
Generate types from YOUR Odoo instance using @kodeme-io/next-core-codegen:
# 1. Install codegen (as dev dependency)
pnpm add -D @kodeme-io/next-core-codegen
# 2. Create configuration file (.next-core.json)
{
"odoo": {
"url": "https://your-odoo.com",
"db": "your_database",
"username": "admin",
"password": "admin"
},
"models": ["res.partner", "sale.order", "sfa.visit"],
"output": "src/types/odoo.ts"
}
# 3. Generate types
npx next-core-codegen generate-types
# 4. Import generated types in your app
import type { ResPartner, SaleOrder } from '@/types/odoo'Generated output structure:
// src/types/odoo.ts (auto-generated)
export type Many2one<T = any> = [number, string] | false
export type One2many = number[]
export type Many2many = number[]
export interface ResPartner {
id?: number
name: string
email?: string
phone?: string
// ... all fields from YOUR Odoo instance
}
export const ResPartnerSchema = z.object({
name: z.string(),
email: z.string().email().optional(),
// ... validation schemas
})Current Package: Reference Types
This package (@kodeme-io/next-core-odoo-types) provides hand-crafted types for common models as:
- Reference implementation - See how types should be structured
- Starting templates - Copy and customize for your needs
- Development aid - Use while setting up codegen
Files in this package:
src/models/
├── base/
│ └── res.partner.ts (hand-crafted example)
├── sales/
│ └── sale.order.ts (hand-crafted example)
└── sfa/
└── sfa.visit.ts (hand-crafted example)🤝 Integration
With MockAdapter
import { MockAdapter } from '@next-core/shared-mock-data'
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
import { SfaVisitSchema } from '@kodeme-io/next-core-odoo-types'
const adapter = new MockAdapter()
// Generate type-safe mock data
const visits: SfaVisit[] = generateVisits(100)
// Validate before seeding
visits.forEach(visit => {
SfaVisitSchema.parse(visit) // Ensures mock matches Odoo
})
adapter.seed({ 'sfa.visit': visits })With OdooAdapter
import { OdooAdapter } from '@kodeme-io/next-core-odoo-api'
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
import { SfaVisitSchema } from '@kodeme-io/next-core-odoo-types'
const adapter = new OdooAdapter({
url: 'https://your-odoo.com',
database: 'your-db',
})
// Type-safe data access
const visits = await adapter.searchRead<SfaVisit>(
'sfa.visit',
[['state', '=', 'scheduled']],
['customer_id', 'scheduled_date', 'state']
)
// Validate response
visits.forEach(visit => {
SfaVisitSchema.parse(visit)
})📄 License
MIT
🙏 Credits
Built with ❤️ by the Next-Core Team
Next: See @next-core/shared-mock-data for mock data generation using these types
