UNPKG

@kodeme-io/next-core-codegen

Version:

TypeScript code generation utilities for next-core framework with React Query hooks and API client generation

788 lines (772 loc) 22.5 kB
import { OdooClient } from '@kodeme-io/next-core-odoo-api'; import { Command } from 'commander'; interface ModelSchema { name: string; description: string; fields: Record<string, FieldSchema>; } interface FieldSchema { type: string; string: string; required: boolean; readonly: boolean; relation?: string; selection?: [string, string][]; help?: string; size?: number; digits?: [number, number]; store?: boolean; compute?: string; related?: string; company_dependent?: boolean; } interface IntrospectionOptions { includeInternal?: boolean; includeComputed?: boolean; includeRelated?: boolean; fieldAttributes?: string[]; } declare class OdooIntrospector { private odoo; private options; private readonly defaultAttributes; constructor(odoo: OdooClient, options?: IntrospectionOptions); /** * Introspect models using native fields_get() * This works with ANY Odoo model out of the box! */ introspectModels(modelNames: string[], options?: IntrospectionOptions): Promise<Record<string, ModelSchema>>; /** * Introspect a single model */ introspectModel(modelName: string, options?: IntrospectionOptions): Promise<ModelSchema>; /** * Get basic information about a model */ private getModelInfo; /** * Parse fields from Odoo fields_get() response */ private parseFields; /** * Determine if a field should be skipped based on options */ private shouldSkipField; /** * Discover all available models in the Odoo instance */ discoverModels(options?: { includeTransient?: boolean; includeAbstract?: boolean; excludePatterns?: string[]; }): Promise<string[]>; /** * Discover models using ir.model table */ private discoverModelsFromIrModel; /** * Fallback model discovery using common Odoo models */ private discoverModelsFromFallback; /** * Check if model name matches a pattern */ private matchesPattern; /** * Format model name to a readable description */ private formatModelName; /** * Get field statistics for a model */ getFieldStatistics(modelName: string): Promise<{ totalFields: number; requiredFields: number; readonlyFields: number; relationFields: number; computedFields: number; typeDistribution: Record<string, number>; }>; /** * Validate that generated types would match current Odoo schema */ validateGeneratedTypes(modelNames: string[], generatedTypesPath: string): Promise<{ valid: boolean; issues: Array<{ model: string; field: string; type: 'missing' | 'extra' | 'type_mismatch'; message: string; }>; }>; } interface GeneratorOptions { includeComments?: boolean; includeJSDoc?: boolean; includeTimestamp?: boolean; optionalFields?: boolean; strictNulls?: boolean; exportTypes?: boolean; interfacePrefix?: string; interfaceSuffix?: string; enumForSelection?: boolean; } declare class TypeScriptGenerator { private options; private readonly defaultOptions; constructor(options?: GeneratorOptions); /** * Generate TypeScript code from model schemas */ generate(schemas: Record<string, ModelSchema>): string; /** * Generate TypeScript interface for a model */ private generateInterface; /** * Generate TypeScript field definition */ private generateField; /** * Convert Odoo field type to TypeScript type */ private toTypeScriptType; /** * Get TypeScript type for selection field */ private getSelectionType; /** * Generate selection enums */ private generateSelectionEnums; /** * Convert model name to interface name */ private toInterfaceName; /** * Convert selection string to enum name */ private toEnumName; /** * Convert selection key to enum key */ private toEnumKey; /** * Generate field statistics as comments */ generateStatistics(schemas: Record<string, ModelSchema>): string[]; /** * Generate import statements for related models */ generateImports(schemas: Record<string, ModelSchema>): string[]; } interface HooksGeneratorOptions { includeComments?: boolean; includeJSDoc?: boolean; includeTimestamp?: boolean; apiClientName?: string; queryClientImport?: string; includeOptimisticUpdates?: boolean; includeInfiniteQueries?: boolean; staleTime?: number; cacheTime?: number; } declare class HooksGenerator { private options; private readonly defaultOptions; constructor(options?: HooksGeneratorOptions); /** * Generate React Query hooks from model schemas */ generate(schemas: Record<string, ModelSchema>): string; /** * Generate imports section */ private generateImports; /** * Generate all hooks for a single model */ private generateModelHooks; /** * Generate query keys factory for a model */ private generateQueryKeysFactory; /** * Generate list query hook (e.g., usePartners) */ private generateListHook; /** * Generate detail query hook (e.g., usePartner) */ private generateDetailHook; /** * Generate search hook with custom domain */ private generateSearchHook; /** * Generate create mutation hook */ private generateCreateHook; /** * Generate update mutation hook */ private generateUpdateHook; /** * Generate delete mutation hook */ private generateDeleteHook; /** * Generate infinite query hook for pagination */ private generateInfiniteQueryHook; /** * Convert model name to interface name */ private toInterfaceName; /** * Convert model name to query key prefix */ private toModelKey; } interface ApiClientGeneratorOptions { includeComments?: boolean; includeJSDoc?: boolean; includeTimestamp?: boolean; baseClientName?: string; className?: string; includeAdvancedMethods?: boolean; includeFieldHelpers?: boolean; } declare class ApiClientGenerator { private options; private readonly defaultOptions; constructor(options?: ApiClientGeneratorOptions); /** * Generate API client class from model schema */ generate(modelName: string, schema: ModelSchema): string; /** * Generate imports */ private generateImports; /** * Generate the API client class */ private generateClass; /** * Generate getAll method */ private generateGetAllMethod; /** * Generate getById method */ private generateGetByIdMethod; /** * Generate search method */ private generateSearchMethod; /** * Generate count method */ private generateCountMethod; /** * Generate create method */ private generateCreateMethod; /** * Generate createMany method */ private generateCreateManyMethod; /** * Generate update method */ private generateUpdateMethod; /** * Generate delete method */ private generateDeleteMethod; /** * Generate exists method */ private generateExistsMethod; /** * Generate findOne method */ private generateFindOneMethod; /** * Generate upsert method */ private generateUpsertMethod; /** * Generate batch operation method */ private generateBatchMethod; /** * Generate field-specific helper methods */ private generateFieldHelpers; /** * Convert model name to interface name */ private toInterfaceName; /** * Capitalize first letter */ private capitalize; } interface OdooConfig { url: string; database: string; username: string; password: string; } interface Config { odoo: OdooConfig; models: string[]; output: string; exclude: string[]; } /** * Load configuration from file */ declare function loadConfig(configPath?: string): Config; /** * Create default configuration template */ declare function createDefaultConfig(): Config; /** * Save configuration to file */ declare function saveConfig(config: Config, filePath: string): Promise<void>; /** * Create a simple Odoo client that uses direct API calls * This matches the working approach from the test script */ declare function createDirectOdooClient(config: Config['odoo']): OdooClient; interface GenerateTypesOptions { config?: string; models?: string[]; output?: string; discover?: boolean; exclude?: string[]; includeInternal?: boolean; includeComputed?: boolean; includeRelated?: boolean; dryRun?: boolean; verbose?: boolean; } declare function generateTypes(options: GenerateTypesOptions): Promise<void>; /** * Create CLI command */ declare function createGenerateTypesCommand(): Command; interface GenerateHooksOptions { models: string[]; output: string; url?: string; db?: string; username?: string; password?: string; includeOptimistic?: boolean; includeInfinite?: boolean; staleTime?: number; cacheTime?: number; } /** * Generate React Query hooks for Odoo models */ declare function generateHooks(options: GenerateHooksOptions, client?: OdooClient): Promise<void>; /** * Create CLI command for generating hooks */ declare function createGenerateHooksCommand(): Command; interface GenerateApiClientOptions { model: string; output: string; className?: string; url?: string; db?: string; username?: string; password?: string; includeAdvanced?: boolean; includeFieldHelpers?: boolean; } /** * Generate API client class for an Odoo model */ declare function generateApiClient(options: GenerateApiClientOptions, client?: OdooClient): Promise<void>; /** * Create CLI command for generating API client */ declare function createGenerateApiClientCommand(): Command; /** * Load environment variables from .env file */ declare function loadEnvVars(envPath?: string): void; /** * Substitute environment variables in a string */ declare function substituteEnvVars(str: string): string; /** * Substitute environment variables recursively in an object */ declare function substituteEnvVarsDeep(obj: any): any; /** * Check if all required environment variables are set */ declare function checkRequiredEnvVars(envVars: string[]): void; /** * Security utilities for protecting sensitive information */ /** * Configuration with safe logging representation */ interface SafeConfig extends Omit<Config, 'odoo'> { odoo: SafeOdooConfig; } interface SafeOdooConfig extends Omit<OdooConfig, 'password'> { password: string; password_source?: 'env' | 'config' | 'default'; } /** * Check if a field name is sensitive */ declare function isSensitiveField(fieldName: string): boolean; /** * Redact sensitive values with appropriate masking */ declare function redactValue(value: any, fieldName?: string): any; /** * Mask a sensitive value for logging */ declare function maskSensitiveValue(value: string): string; /** * Create a safe version of configuration for logging */ declare function createSafeConfig(config: Config): SafeConfig; /** * Sanitize a password value for safe logging */ declare function sanitizePassword(password: string): string; /** * Sanitize an object recursively for safe logging */ declare function sanitizeObject(obj: any, maxDepth?: number, currentDepth?: number): any; /** * Sanitize URL to remove sensitive query parameters */ declare function sanitizeUrl(url: string): string; /** * Format configuration for verbose logging */ declare function formatConfigForLogging(config: Config): string[]; /** * Performance monitoring and optimization utilities */ interface PerformanceMetrics { duration: number; memoryUsage?: NodeJS.MemoryUsage; cpuUsage?: NodeJS.CpuUsage; operationCount?: number; errorCount?: number; timestamp: number; } interface PerformanceTracker { start: () => void; end: () => PerformanceMetrics; checkpoint: (name: string) => void; getCheckpoints: () => Array<{ name: string; time: number; }>; incrementOperationCount: () => void; incrementErrorCount: () => void; } interface BatchProcessorOptions<T> { batchSize: number; maxConcurrency?: number; progressCallback?: (completed: number, total: number) => void; errorHandler?: (error: Error, item: T, index: number) => void; } interface CacheOptions { maxSize: number; ttl: number; enableMetrics?: boolean; } /** * Create a performance tracker for monitoring operations */ declare function createPerformanceTracker(): PerformanceTracker; /** * Create a simple in-memory cache with TTL support */ declare function createCache<T>(options: CacheOptions): { get(key: string): T | undefined; set(key: string, value: T): void; has(key: string): boolean; delete(key: string): boolean; clear(): void; size(): number; getMetrics(): { size: number; hitRate: number; hits: number; misses: number; evictions: number; }; getEntries(): Array<{ key: string; value: T; hits: number; age: number; }>; }; /** * Batch processor for handling large operations efficiently */ declare function createBatchProcessor<T, R>(processor: (items: T[], batchIndex: number) => Promise<R[]>, options: BatchProcessorOptions<T>): { process(items: T[]): Promise<R[]>; }; /** * Memory usage monitor for detecting memory leaks */ declare function createMemoryMonitor(): { start(sampleIntervalMs?: number): void; stop(): void; getSamples(): { timestamp: number; usage: NodeJS.MemoryUsage; }[]; getTrend(): { heapTrend: number; rssTrend: number; duration: number; sampleCount: number; increasing: boolean; } | null; isMemoryLeaking(thresholdMb?: number): boolean; }; /** * Utility function to measure execution time of any function */ declare function measureExecutionTime<T>(fn: () => T | Promise<T>, tracker?: PerformanceTracker): Promise<{ result: T; metrics: PerformanceMetrics; }>; /** * Create a rate limiter to prevent overwhelming external services */ declare function createRateLimiter(maxRequests: number, windowMs: number): { checkLimit(): Promise<boolean>; waitForSlot(): Promise<void>; getStats(): { requestsInWindow: number; maxRequests: number; windowMs: number; resetTime: number; }; }; /** * Performance optimization suggestions based on metrics */ declare function analyzePerformance(metrics: PerformanceMetrics): string[]; /** * Enhanced error types for codegen package */ /** * Base error class for all codegen errors */ declare abstract class CodeGenError extends Error { readonly details?: any | undefined; abstract readonly code: string; abstract readonly category: 'CONFIG' | 'NETWORK' | 'GENERATION' | 'VALIDATION' | 'FILE_SYSTEM' | 'SECURITY'; constructor(message: string, details?: any | undefined); /** * Get a user-friendly error message */ abstract getUserMessage(): string; /** * Get suggestions for resolving the error */ abstract getSuggestions(): string[]; /** * Check if this error is recoverable */ isRecoverable(): boolean; /** * Convert to JSON for logging/serialization */ toJSON(): { name: string; code: string; category: "CONFIG" | "NETWORK" | "GENERATION" | "VALIDATION" | "FILE_SYSTEM" | "SECURITY"; message: string; userMessage: string; suggestions: string[]; recoverable: boolean; details: any; stack: string | undefined; }; } /** * Configuration related errors */ declare class ConfigurationError extends CodeGenError { readonly code: string; readonly category: "CONFIG"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; } /** * Network related errors */ declare class NetworkError extends CodeGenError { readonly code: string; readonly category: "NETWORK"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; isRecoverable(): boolean; } /** * Code generation related errors */ declare class GenerationError extends CodeGenError { readonly code: string; readonly category: "GENERATION"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; isRecoverable(): boolean; } /** * Validation related errors */ declare class ValidationError extends CodeGenError { readonly code: string; readonly category: "VALIDATION"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; } /** * File system related errors */ declare class FileSystemError extends CodeGenError { readonly code: string; readonly category: "FILE_SYSTEM"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; isRecoverable(): boolean; } /** * Security related errors */ declare class SecurityError extends CodeGenError { readonly code: string; readonly category: "SECURITY"; constructor(code: string, message: string, details?: any); getUserMessage(): string; getSuggestions(): string[]; } /** * Error factory functions for creating specific error types */ declare const ErrorFactory: { configurationNotFound: (filePath?: string) => ConfigurationError; configurationInvalid: (reason: string, details?: any) => ConfigurationError; networkConnectionFailed: (url: string, originalError?: Error) => NetworkError; networkTimeout: (url: string, timeout: number) => NetworkError; authenticationFailed: (username: string) => NetworkError; permissionDenied: (model?: string) => NetworkError; modelNotFound: (models: string[]) => GenerationError; fieldTypeUnsupported: (fieldType: string, model: string, field: string) => GenerationError; outputWriteFailed: (filePath: string, originalError?: Error) => GenerationError; validationFailed: (field: string, value: string, reason: string) => ValidationError; filePermissionDenied: (path: string, operation: string) => FileSystemError; insecureUrl: (url: string) => SecurityError; }; /** * Utility function to determine if an error is a codegen error */ declare function isCodeGenError(error: any): error is CodeGenError; /** * Utility function to wrap unknown errors in a CodeGenError */ declare function wrapError(error: any, context?: string): CodeGenError; /** * Input validation utilities for security */ /** * Validation result interface */ interface ValidationResult { isValid: boolean; errors: string[]; warnings: string[]; } /** * Configuration validation schema */ interface ValidationRule { field: string; required?: boolean; type: 'string' | 'number' | 'boolean' | 'array' | 'object' | 'url' | 'email' | 'path'; pattern?: RegExp; minLength?: number; maxLength?: number; min?: number; max?: number; allowedValues?: any[]; custom?: (value: any) => string | null; } /** * Validate URLs for security and proper format */ declare function validateUrl(url: string, options?: { allowHttpsOnly?: boolean; allowLocalhost?: boolean; allowedDomains?: string[]; maxUrlLength?: number; }): ValidationResult; /** * Validate file paths for security */ declare function validatePath(filePath: string, options?: { allowAbsolute?: boolean; allowRelative?: boolean; allowedExtensions?: string[]; maxPathLength?: number; preventPathTraversal?: boolean; }): ValidationResult; /** * Validate model names for Odoo compatibility */ declare function validateModelName(modelName: string): ValidationResult; /** * Validate configuration object against validation rules */ declare function validateConfig(config: any, rules: ValidationRule[]): ValidationResult; /** * Sanitize and validate user input */ declare function sanitizeInput(input: string, options?: { allowHtml?: boolean; maxLength?: number; allowedChars?: RegExp; removeWhitespace?: boolean; trim?: boolean; }): ValidationResult & { sanitized: string; }; /** * Validate environment variable names and values */ declare function validateEnvironmentVariable(name: string, value: string): ValidationResult; /** * Comprehensive validation for Odoo configuration */ declare function validateOdooConfig(config: any): ValidationResult; export { ApiClientGenerator, type ApiClientGeneratorOptions, type BatchProcessorOptions, type CacheOptions, CodeGenError, type Config, ConfigurationError, ErrorFactory, type FieldSchema, FileSystemError, type GenerateTypesOptions, GenerationError, type GeneratorOptions, HooksGenerator, type HooksGeneratorOptions, type IntrospectionOptions, type ModelSchema, NetworkError, type OdooConfig, OdooIntrospector, type PerformanceMetrics, type PerformanceTracker, SecurityError, TypeScriptGenerator, ValidationError, type ValidationResult, type ValidationRule, analyzePerformance, checkRequiredEnvVars, createBatchProcessor, createCache, createDefaultConfig, createDirectOdooClient, createGenerateApiClientCommand, createGenerateHooksCommand, createGenerateTypesCommand, createMemoryMonitor, createPerformanceTracker, createRateLimiter, createSafeConfig, formatConfigForLogging, generateApiClient, generateHooks, generateTypes, isCodeGenError, isSensitiveField, loadConfig, loadEnvVars, maskSensitiveValue, measureExecutionTime, redactValue, sanitizeInput, sanitizeObject, sanitizePassword, sanitizeUrl, saveConfig, substituteEnvVars, substituteEnvVarsDeep, validateConfig, validateEnvironmentVariable, validateModelName, validateOdooConfig, validatePath, validateUrl, wrapError };