UNPKG

@horizon-apps/domain-schema-core

Version:

Core domain schema utilities for Horizon Platform - Schema generators, data enrichers, converters and specifications

1,413 lines (1,367 loc) 38.8 kB
/** * 🎯 Types - Definições de Tipos para o Motor de Enriquecimento * * Interfaces e tipos TypeScript para o formato SSOT * com suporte a contextos separados e estrutura flat * * @module types */ /** * Contexto de regras e relações */ interface RulesContext { parent?: string; conditions?: string[]; } /** * Contexto de validação (backend/Zod) */ interface ValidationContext { required?: boolean; min?: number; max?: number; minLength?: number; maxLength?: number; precision?: number; } /** * Contexto de banco de dados */ interface DbContext { type?: string; unique?: boolean; index?: boolean | string; default?: any; primary?: boolean; autoincrement?: boolean; geoSource?: string[]; } /** * Contexto de interface e experiência */ interface UiContext { label?: string; description?: string; placeholder?: string; iconName?: string; displayTemplate?: string; mask?: string; searchable?: boolean; filterable?: boolean; sortable?: boolean; } /** * Contexto de auditoria e rastreamento */ interface AuditContext { origin?: string; modifiedBy?: string[]; } /** * Estrutura completa de metadados SSOT */ interface FieldMetadata$1 { key: string; type: "String" | "Number" | "Boolean" | "String[]" | "Json" | "Json[]" | "Relation"; enum?: Record<string, string>; format?: "currency" | "date" | "datetime" | "area" | "distance" | "percent" | "count" | "year" | "geo-point"; unit?: string; categories?: string[]; rules?: RulesContext; validation?: ValidationContext; db?: DbContext; ui?: UiContext; audit?: AuditContext; } /** * Campo enriquecido após processamento - ESTRUTURA ENXUTA PARA DISPLAY */ interface EnrichedField { key: string; value: any; label: string; valueLabel?: string | string[]; displayLabel?: string; iconName?: string; icon?: string; categories?: string[]; type?: string; format?: string; unit?: string; metadata?: { type?: string; format?: string; unit?: string; validation?: ValidationContext; ui?: UiContext; audit?: AuditContext; enum?: Record<string, string>; rules?: RulesContext; db?: DbContext; }; } /** * Resultado do EnrichMapper de cada domínio */ interface EnrichMapperResult { data: Record<string, any>; schema: FieldMetadata$1[]; computedSchema: FieldMetadata$1[]; computedData: Record<string, any>; } /** * Função de enriquecimento específica de cada domínio */ type EnrichMapper = (rawData: Record<string, any>) => EnrichMapperResult; /** * Configuração de um domínio no registry */ interface DomainConfig { key: string; enrichMapper: EnrichMapper; } /** * Registry completo de domínios */ type DomainRegistry = Record<string, DomainConfig>; /** * Opções para o processo de enriquecimento */ interface EnrichmentOptions { locale?: string; currency?: string; includeMetadata?: boolean; getIcon?: (iconName: string) => string; } /** * Estrutura de dados enriquecidos (flat) */ interface EnrichedData { [key: string]: EnrichedField | EnrichedData | EnrichedData[] | Record<string, EnrichedField>; } /** * 🚀 Domain Enricher Engine - Motor Principal de Enriquecimento v2.0 * * Classe principal que gerencia o enriquecimento de dados de domínios * com suporte a relacionamentos nested e campos computados * * @module domain-enricher-engine * @version 2.0.0 */ /** * Motor principal de enriquecimento de dados * * @example * ```typescript * const enricher = new DomainDataDisplayEnricher(registry, options); * const enrichedData = enricher.enrich(rawData, "property"); * ``` */ declare class DomainDataDisplayEnricher { private registry; private options; /** * Construtor do motor de enriquecimento * * @param registry - Registry com configurações de todos os domínios * @param options - Opções globais de enriquecimento */ constructor(registry: DomainRegistry, options?: EnrichmentOptions); /** * Enriquece dados de um domínio específico * * @param rawData - Dados brutos do banco/API * @param domainKey - Chave do domínio (ex: "property", "broker") * @returns Dados enriquecidos com estrutura flat */ enrich(rawData: Record<string, any>, domainKey: string): EnrichedData; /** * Enriquece uma lista inteira de dados * * @param rawDataArray - Array de dados brutos * @param domainKey - Chave do domínio ("property", "broker", etc.) * @returns Array de dados enriquecidos */ enrichList(rawDataArray: any[], domainKey: string): EnrichedData[]; /** * Converte array de fields para formato indexado interno */ private arrayToIndexedSchema; /** * Processa campos principais (incluindo relacionamentos) */ private processMainFields; /** * Processa campos computados */ private processComputedFields; /** * Atualiza o registry em runtime * * @param domainKey - Chave do domínio * @param config - Nova configuração do domínio */ registerDomain(domainKey: string, config: any): void; /** * Remove um domínio do registry * * @param domainKey - Chave do domínio a remover */ unregisterDomain(domainKey: string): void; /** * Atualiza opções globais * * @param options - Novas opções */ updateOptions(options: Partial<EnrichmentOptions>): void; /** * Obtém o registry atual */ getRegistry(): DomainRegistry; /** * Obtém as opções atuais */ getOptions(): EnrichmentOptions; } /** * 🎨 Field Enricher - Enriquecimento de Campo Individual * * Função isolada para enriquecer um único campo com seus metadados * Preserva toda a lógica de formatação e processamento de templates * * @module field-enricher * @version 2.0.0 */ /** * Formata valor monetário */ declare function formatCurrency(value: number | string | null, currency?: string, locale?: string): string; /** * Formata data */ declare function formatDateTime(value: string | Date, locale?: string): string; /** * Formata área com unidade */ declare function formatArea(value: number | string, unit?: string): string; /** * Formata distância com unidade */ declare function formatDistance(value: number | string, unit?: string): string; /** * Formata porcentagem */ declare function formatPercent(value: number | string): string; /** * Formata contagem (números inteiros) */ declare function formatCount(value: number | string): string; /** * Formata ano */ declare function formatYear(value: number | string): string; /** * Processa template com pluralização e substituições */ declare function processTemplate(template: string | undefined, value: any, valueLabel: string | string[] | undefined): string | undefined; declare const formatters: { currency: typeof formatCurrency; date: typeof formatDateTime; area: typeof formatArea; distance: typeof formatDistance; percent: typeof formatPercent; count: typeof formatCount; year: typeof formatYear; }; declare const templateProcessor: typeof processTemplate; /** * 🎣 React Hooks para Domain Data Display Enricher * * Hooks customizados para facilitar uso do enricher em React * * @module hooks * @version 2.0.0 */ /** * Hook para enriquecer uma lista de dados automaticamente * * @param rawData - Array de dados brutos * @param domainKey - Chave do domínio ("property", "broker", etc.) * @param registry - Registry de domínios * @param options - Opções de enriquecimento (opcional) * @returns { enrichedData, loading, error } */ declare function useEnrichList(rawData: any[], domainKey: string, registry: DomainRegistry, options?: Partial<EnrichmentOptions>): { enrichedData: EnrichedData[]; loading: boolean; error: Error | null; }; /** * Hook para enriquecer um único item * * @param rawData - Dados brutos * @param domainKey - Chave do domínio * @param registry - Registry de domínios * @param options - Opções de enriquecimento (opcional) * @returns { enrichedData, loading, error } */ declare function useEnrich(rawData: any, domainKey: string, registry: DomainRegistry, options?: Partial<EnrichmentOptions>): { enrichedData: EnrichedData | null; loading: boolean; error: Error | null; }; /** * Hook para criar uma instância persistente do enricher * * @param registry - Registry de domínios * @param options - Opções de enriquecimento (opcional) * @returns instância do DomainDataDisplayEnricher */ declare function useEnricher(registry: DomainRegistry, options?: Partial<EnrichmentOptions>): DomainDataDisplayEnricher; /** * JsonToZodGenerator - Converte schemas Horizon Fields Metadata Pattern v2.2.0 para Zod * * Suporta o novo formato com: * - categories (ao invés de tags) * - validation.precision para decimais * - enum como object * - mask para validações automáticas * - conditions para campos condicionais * - parent para hierarquias * - db metadata (ignorado na geração Zod) * - Inferência inteligente */ interface HorizonFieldDefinition { key: string; type: "String" | "String[]" | "Number" | "Boolean" | "Json" | "Json[]" | "Array"; label: string; categories?: string[]; validation?: { required?: boolean; min?: number; max?: number; minLength?: number; maxLength?: number; precision?: number; }; format?: "currency" | "area" | "distance" | "count" | "percent" | "date" | "datetime" | "time"; unit?: string; mask?: "cpf" | "cnpj" | "cep" | "phone" | "email" | "url"; enum?: Record<string, string>; conditions?: string[]; parent?: string; searchable?: boolean; filterable?: boolean; sortable?: boolean; db?: { type?: string; unique?: boolean; index?: boolean | string; default?: any; }; origin?: string; modifiedBy?: string[]; } interface JsonToZodOptions { schemaName: string; addDescriptions?: boolean; addValidationMessages?: boolean; exportType?: boolean; sortFields?: boolean; enablePrecisionValidation?: boolean; logInference?: boolean; } declare class JsonToZodGenerator { private static inferenceLog; /** * Aplica inferência inteligente em um campo */ private static applyInference; private static log; /** * Converte um campo para Zod */ private static fieldToZod; /** * Gera o schema Zod completo */ static generate(fields: HorizonFieldDefinition[], options: JsonToZodOptions): string; /** * Gera schema a partir de arquivo JSON v2.2.0 */ static generateFromFile(jsonPath: string, options: JsonToZodOptions): Promise<string>; /** * Salva o schema gerado */ static saveToFile(fields: HorizonFieldDefinition[], options: JsonToZodOptions, outputPath: string): Promise<void>; /** * Analisa um schema e retorna estatísticas */ static analyzeSchema(fields: HorizonFieldDefinition[]): { totalFields: number; fieldTypes: Record<string, number>; fieldFormats: Record<string, number>; fieldCategories: Record<string, number>; requiredFields: number; fieldsWithValidation: number; fieldsWithMask: number; fieldsWithEnum: number; fieldsWithConditions: number; fieldsWithParent: number; }; } /** * 🔍 Horizon Domain Data Filters * * Funções utilitárias para filtrar e selecionar campos de dados de domínio * Compatível com formato array e objeto enriquecido * * @module horizon-domain-data-filters * @version 1.0.0 */ interface Field$1 { key: string; value?: any; label?: string; type?: string; category?: string | string[]; categories?: string | string[]; [key: string]: any; } type FieldsArray = Field$1[]; type FieldsObject = Record<string, Field$1>; type FieldsInput = FieldsArray | FieldsObject; /** * Filtra campos por categoria(s) * * @param fields - Array de campos ou objeto de campos enriquecidos * @param category - String de categoria única ou array de categorias * @param asObject - Se true, retorna como objeto; se false, retorna como array * @param preserveOrder - Se true, preserva a ordem das categorias solicitadas (padrão: false) * @returns Campos filtrados como array ou objeto * * @example * // Filtrar por categoria única * const mainFields = getFieldsByCategory(fields, 'main'); * * @example * // Filtrar por múltiplas categorias * const valueFields = getFieldsByCategory(fields, ['pricing', 'values']); * * @example * // Retornar como objeto * const fieldsObj = getFieldsByCategory(fields, 'main', true); * * @example * // Preservar ordem das categorias solicitadas * const orderedFields = getFieldsByCategory(fields, ['pricing', 'dimensions'], false, true); * // Retorna todos os campos 'pricing' primeiro, depois todos os 'dimensions' */ declare function getFieldsByCategory(fields: FieldsInput, category: string | string[], asObject?: boolean, preserveOrder?: boolean): FieldsArray | FieldsObject; /** * Filtra campos por lista de keys, mantendo a ordem especificada * Retorna apenas campos com valores válidos (não null, undefined, empty string ou NaN) * * @param fields - Array de campos ou objeto de campos enriquecidos * @param keys - Array de keys na ordem desejada * @param asObject - Se true, retorna como objeto; se false, retorna como array (padrão) * @returns Array ou objeto de campos na ordem das keys, apenas com valores válidos * * @example * // Buscar campos específicos na ordem desejada (array) * const orderedFields = getFieldsByKeys(fields, ['valor_venda', 'area_total', 'dormitorios']); * * @example * // Retornar como objeto para lookup rápido * const fieldsObj = getFieldsByKeys(fields, ['valor_venda', 'area_total'], true); * * @example * // Campos sem valores válidos são ignorados * const validFields = getFieldsByKeys(fields, ['field1', 'field2', 'field3']); * // Se field2.value for null, ele não aparece no resultado */ declare function getFieldsByKeys(fields: FieldsInput, keys: string[], asObject?: boolean): FieldsArray | FieldsObject; /** * 🔄 Horizon Domain Data Transformers * * Funções para transformar estruturas de dados de domínio * * @module horizon-domain-data-transformers * @version 1.0.0 */ interface Field { key: string; value?: any; label?: string; type?: string; [key: string]: any; } /** * Expande um campo array em múltiplos campos booleanos * Cada item do array se torna um campo independente com value: true * * @param field - Campo com value array ou diretamente um array de strings * @returns Array de campos booleanos * * @example * // Passando campo completo * const field = { key: 'amenities', value: ['pool', 'gym', 'parking'] }; * const booleans = expandArrayFieldToBoolean(field); * // Resultado: [ * // { key: 'pool', value: true, type: 'Boolean', label: 'pool' }, * // { key: 'gym', value: true, type: 'Boolean', label: 'gym' }, * // { key: 'parking', value: true, type: 'Boolean', label: 'parking' } * // ] * * @example * // Passando array direto * const booleans = expandArrayFieldToBoolean(['wifi', 'ac', 'tv']); * // Resultado: [ * // { key: 'wifi', value: true, type: 'Boolean', label: 'wifi' }, * // { key: 'ac', value: true, type: 'Boolean', label: 'ac' }, * // { key: 'tv', value: true, type: 'Boolean', label: 'tv' } * // ] * * @example * // Uso direto com propriedade * const property = { amenities: { key: 'amenities', value: ['pool', 'gym'] } }; * const booleans = expandArrayFieldToBoolean(property.amenities); */ declare function expandArrayFieldToBoolean(field: Field | string[]): Field[]; /** * Ordena um array de objetos baseado em múltiplos campos e direções * * @param fields - Array de objetos para ordenar * @param sortKeys - Array de strings no formato "campo:direção" (ex: ["name:asc", "price:desc"]) * @returns Array ordenado (nova instância, não modifica o original) * * @example * // Ordenar por nome crescente, depois preço decrescente * const products = [ * { name: "Casa A", price: 300000, area: 120 }, * { name: "Casa B", price: 250000, area: 100 }, * { name: "Casa A", price: 280000, area: 110 } * ]; * * const sorted = sortFields(products, ["name:asc", "price:desc"]); * // Resultado: Casa A (300k), Casa A (280k), Casa B (250k) * * @example * // Ordenar apenas por um campo * const sorted = sortFields(products, ["area:desc"]); */ declare function sortFields(fields: any[], sortKeys?: string[]): any[]; /** * 🎯 URL State Serializer V2 - Interfaces * * Sistema baseado em resolvers configuráveis para serialização de estado */ /** * Interface base para todos os resolvers */ interface IResolver { /** * Serializa um valor para query string params * @returns Array de strings no formato "key=value" */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para o valor original * @param params - Todos os parâmetros da query string * @param key - Chave do campo sendo deserializado */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * Identificador de formato JSON para o FieldsResolver */ interface IJsonIdentifier { /** * Nome do identificador (ex: "range", "between") */ name: string; /** * Detecta se um objeto JSON corresponde a este formato */ detect(value: any): boolean; /** * Serializa o JSON identificado para query params */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para o formato JSON original */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * Configuração de um campo para o serializer */ interface FieldConfig { /** * Nome do resolver a usar */ resolver: string; /** * Alias para o campo na URL (ex: fts -> q) */ alias?: string; /** * Para FieldsResolver: identificadores JSON disponíveis */ jsonIdentifiers?: string[]; /** * Para FieldsResolver: resolver para JSON não identificado */ unknownJson?: string; /** * Configurações adicionais específicas do resolver */ options?: Record<string, any>; } /** * Configuração completa do serializer */ interface SerializerConfig { /** * Configuração de cada campo * Key = nome do campo no estado * Value = configuração do campo */ [fieldName: string]: FieldConfig; } /** * Estado genérico de entrada/saída */ interface SearchState { /** * Filtros de busca que serão flattened na URL */ filters?: Record<string, any>; /** * Full-text search */ fts?: string; /** * Geometria/localização (será implementado depois) */ geom?: any; /** * Paginação */ page?: number; limit?: number; /** * Ordenação */ sort?: Record<string, 'asc' | 'desc'>; /** * Nível de zoom */ zoom?: number; /** * Centro do mapa */ center?: { lat: number; lng: number; }; /** * Bounding box */ bbox?: { top: number; left: number; right: number; bottom: number; }; /** * Layout de exibição */ layout?: string; /** * Tipo de card */ card?: string; /** * Outros campos customizados */ [key: string]: any; } /** * 🎯 URL State Serializer V2 * * Sistema baseado em resolvers configuráveis * Responsável por Estado ↔ Query String */ declare class UrlStateSerializer { private config; private resolvers; constructor(config: SerializerConfig); /** * Inicializa resolvers baseado na configuração */ private initializeResolvers; /** * Serializa estado para query string */ serialize(state: SearchState): string; /** * Deserializa query string para estado */ deserialize(queryString: string): SearchState; /** * Parse de query string para objeto de params */ private parseQueryString; /** * Configuração padrão recomendada */ static getDefaultConfig(): SerializerConfig; } /** * 🎯 Base Resolver - Classe abstrata para todos os resolvers */ declare abstract class BaseResolver implements IResolver { protected config: FieldConfig; constructor(config?: FieldConfig); /** * Obtém o nome do campo para usar na URL (considera alias) */ protected getUrlKey(key: string): string; /** * Serializa um valor para query string params */ abstract serialize(key: string, value: any): string[]; /** * Deserializa de volta para o valor original */ abstract deserialize(params: Record<string, string | string[]>, key: string): any; /** * Helper para encodar valores na URL */ protected encodeValue(value: any): string; /** * Helper para criar param no formato key=value */ protected createParam(key: string, value: any): string; } /** * 🎯 Fields Resolver * * Processa o campo "fields" fazendo flatten para a raiz da URL * Aplica identificadores JSON configurados para valores complexos */ declare class FieldsResolver extends BaseResolver { private base64Resolver; constructor(config?: FieldConfig); /** * Serializa campos internos de "fields" para a raiz da URL */ serialize(_key: string, value: any): string[]; /** * Deserializa params da URL de volta para o objeto fields */ deserialize(params: Record<string, string | string[]>, _key: string): any; /** * Verifica se é valor simples */ private isSimpleValue; /** * Identifica formato JSON e serializa apropriadamente */ private identifyAndSerialize; /** * Verifica se é campo especial (não pertence ao fields) */ private isSpecialField; /** * Parse de valor simples com detecção de tipo */ private parseSimpleValue; /** * Detecta se parece ser um endereço */ private isLikelyAddress; /** * Verifica se as partes contêm números (indicativo de endereço/medida) */ private hasNumericParts; /** * Converte string para tipo apropriado */ private convertValue; } /** * 🎯 Simple Value Resolver * * Processa valores simples (string, number, boolean) * Suporta alias configurável */ declare class SimpleValueResolver extends BaseResolver { /** * Serializa valor simples para URL * Ex: fts="casa moderna" → ["q=casa+moderna"] */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para valor simples */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Pagination Sort Resolver * * Converte objetos de ordenação para formato URL amigável * Suporta múltiplos campos de ordenação */ declare class PaginationSortResolver extends BaseResolver { /** * Serializa objeto de sort para URL * Ex: { price: "desc", date: "asc" } → ["sort=price:desc,date:asc"] */ serialize(key: string, value: any): string[]; /** * Deserializa string de sort para objeto * Ex: "price:desc,date:asc" → { price: "desc", date: "asc" } */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Lat/Lng Resolver * * Converte objetos com latitude/longitude para params separados * Ex: center: {lat: -25, lng: -50} → center_lat=-25&center_lng=-50 */ declare class LatLngResolver extends BaseResolver { /** * Serializa objeto lat/lng para params separados */ serialize(key: string, value: any): string[]; /** * Deserializa params separados para objeto lat/lng */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Base64 Resolver * * Fallback para JSONs complexos não identificados * Serializa qualquer objeto/array como base64 */ declare class Base64Resolver extends BaseResolver { /** * Serializa valor complexo para base64 */ serialize(key: string, value: any): string[]; /** * Deserializa base64 de volta para valor original */ deserialize(params: Record<string, string | string[]>, key: string): any; /** * Converte string para base64 (compatível com browser e Node.js) */ private toBase64; /** * Converte base64 para string (compatível com browser e Node.js) */ private fromBase64; } /** * 🎯 Passthrough Resolver * * Resolver simples que passa valores direto sem transformação * Usado para page, limit, zoom, layout, card, etc */ declare class PassthroughResolver extends BaseResolver { /** * Serializa valor direto para URL */ serialize(key: string, value: any): string[]; /** * Deserializa valor direto da URL */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Range Identifier * * Identifica e processa objetos com gte/lte * Ex: { gte: 100, lte: 500 } → campo[min]=100&campo[max]=500 */ declare class RangeIdentifier implements IJsonIdentifier { name: string; /** * Detecta se é um objeto range (tem gte ou lte) */ detect(value: any): boolean; /** * Serializa para formato [min]/[max] */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para objeto com gte/lte */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Between Identifier * * Identifica objetos range e serializa como único param * Ex: { gte: 100, lte: 500 } → campo[entre]=100,500 */ declare class BetweenIdentifier implements IJsonIdentifier { name: string; /** * Detecta se é um objeto com AMBOS gte E lte */ detect(value: any): boolean; /** * Serializa para formato [entre]=min,max */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para objeto com gte/lte */ deserialize(params: Record<string, string | string[]>, key: string): any; } /** * 🎯 Min/Max Identifier * * Identifica objetos com min/max explícitos * Ex: { min: 100, max: 500 } → campo[min]=100&campo[max]=500 */ declare class MinMaxIdentifier implements IJsonIdentifier { name: string; /** * Detecta se é um objeto com min ou max */ detect(value: any): boolean; /** * Serializa para formato [min]/[max] */ serialize(key: string, value: any): string[]; /** * Deserializa de volta para objeto com min/max */ deserialize(params: Record<string, string | string[]>, key: string): any; } declare const defaultConfig$1: SerializerConfig; /** * 🎯 SEO Slug Generator - Interfaces * * Sistema leve para geração de slugs SEO a partir de campos de busca */ /** * Configuração de campos para extração */ interface FieldsConfig { /** * Mapeamento de campos lógicos para possíveis nomes nos dados * Ex: { tipo: ['tipo', 'type'], cidade: ['cidade', 'city'] } */ [logicalField: string]: string[]; } /** * Opções do gerador de slug */ interface SlugOptions { /** * Prefixo para o slug (ex: 'imoveis') */ prefix?: string; /** * Tamanho máximo do slug (padrão: 80) */ maxLength?: number; /** * Número mínimo de partes para gerar slug (padrão: 2) */ minParts?: number; /** * Separador entre partes: 'dash' (-) ou 'slash' (/) para URLs hierárquicas */ separator?: 'dash' | 'slash' | string; } /** * Configuração completa do gerador */ interface SlugGeneratorConfig { /** * Configuração de campos a serem extraídos */ fields: FieldsConfig; /** * Ordem de extração dos campos (prioridade) */ order: string[]; /** * Opções adicionais */ options?: SlugOptions; } /** * Estado de busca de entrada (formato fields do URL Parser V2) */ interface SearchFields { /** * Campos de busca (mesmo formato do URL Parser V2) */ [fieldName: string]: any; } /** * Resultado da geração de slug */ interface SlugResult { /** * Slug gerado (null se não foi possível gerar) */ slug: string | null; /** * Partes extraídas dos campos */ parts: string[]; /** * Campos que foram encontrados e utilizados */ usedFields: Record<string, string>; /** * Campos configurados mas não encontrados */ missingFields: string[]; } /** * Resultado com análise de potencial (opcional) */ interface SlugAnalysisResult extends SlugResult { /** * Qualidade do slug baseado nos campos disponíveis */ quality: 'high' | 'medium' | 'low' | 'none'; /** * Sugestões para melhorar o slug */ suggestions: string[]; } /** * 🎯 SEO Slug Generator - Classe principal * * Gera slugs SEO a partir de campos de busca de forma configurável */ declare class SlugGenerator { private config; private extractor; private options; constructor(config: SlugGeneratorConfig); /** * Resolve o separador baseado na configuração */ private resolveSeparator; /** * Formata valor do campo para melhor legibilidade na URL */ private formatFieldValue; /** * Gera slug simples a partir dos campos de busca */ generate(searchFields: SearchFields): string | null; /** * Gera slug com detalhes completos do processo */ generateWithDetails(searchFields: SearchFields): SlugResult; /** * Gera slug com análise de qualidade (opcional) */ generateWithAnalysis(searchFields: SearchFields): SlugAnalysisResult; /** * Analisa a qualidade do slug baseado nos campos disponíveis */ private analyzeQuality; /** * Gera sugestões para melhorar o slug */ private generateSuggestions; /** * Valida slug considerando separador customizado */ private isValidSlugForSeparator; /** * Testa a configuração com dados de exemplo */ testConfiguration(testData: SearchFields): { config: SlugGeneratorConfig; result: SlugAnalysisResult; extractedFields: Record<string, string>; }; } /** * 🎯 Slugify Simples - Sem dependências pesadas * * Normaliza texto para formato URL-friendly usando apenas JavaScript nativo */ /** * Normaliza texto para slug URL-safe usando apenas JS nativo * Remove acentos, caracteres especiais e formata para slug */ declare function slugify(text: string | number, preserveSlash?: boolean): string; /** * Trunca slug mantendo palavras completas * Evita cortar no meio de uma palavra */ declare function truncateSlug(slug: string, maxLength: number, separator?: string): string; /** * Valida se um slug está no formato correto */ declare function isValidSlug(slug: string): boolean; /** * 🎯 Field Extractor - Extração de valores dos campos * * Extrai valores dos campos de busca baseado na configuração */ /** * Extrator de campos - responsável por encontrar valores nos dados de entrada */ declare class FieldExtractor { private fieldsConfig; constructor(fieldsConfig: FieldsConfig); /** * Extrai valor de um campo lógico dos dados de entrada * Procura por diferentes nomes de campo conforme configuração */ extractField(logicalField: string, searchFields: SearchFields): string | null; /** * Extrai valor de um campo específico, lidando com diferentes tipos */ private extractFieldValue; /** * Extrai todos os campos configurados de uma vez * Retorna mapa com campos encontrados e valores */ extractAllFields(searchFields: SearchFields): Record<string, string>; /** * Lista os campos configurados que não foram encontrados nos dados */ getMissingFields(searchFields: SearchFields): string[]; } /** * 🎯 SEO Slug Generator * * Sistema leve para geração de slugs SEO a partir de campos de busca */ declare const defaultImoveisConfig: SlugGeneratorConfig; declare const defaultConfig: SlugGeneratorConfig; /** * 🎯 Search State Enricher - Interfaces * * Enriquece estado da URL com operadores baseado em schema */ /** * Tipos de campo suportados */ type FieldType = 'select' | 'multiselect' | 'range' | 'search' | 'boolean' | 'date' | 'daterange' | 'radio' | 'slider' | 'tags' | 'autocomplete'; /** * Tipos de operador suportados */ type OperatorType = 'and' | 'or' | 'equals' | 'contains' | 'between' | 'gte' | 'lte' | 'gt' | 'lt' | 'in' | 'not'; /** * Metadata de campo individual (formato do Search Schema Specification) */ interface FieldMetadata { key: string; label?: string; type: FieldType; operator?: OperatorType; multiple?: boolean; default?: any; required?: boolean; parent?: string; when?: string; disabled?: string; options?: any[]; optionsSource?: 'static' | 'faceted' | 'api'; onChange?: 'submit' | 'default'; debounce?: number; min?: number; max?: number; minLength?: number; maxLength?: number; pattern?: string; } /** * Metadata de FTS (root field) */ interface FtsMetadata { placeholder?: string; operator?: 'websearch' | 'plainto' | 'phrase' | 'boolean'; debounce?: number; minLength?: number; onChange?: 'submit' | 'default'; } /** * Metadata de Geom (root field) */ interface GeomMetadata { operation?: 'within' | 'intersects' | 'near'; defaultZoom?: number; defaultCenter?: { lat: number; lng: number; }; enableDrawing?: boolean; enableClustering?: boolean; } /** * Schema completo de busca (formato Search Schema Specification) */ interface SearchSchema { filters: Record<string, FieldMetadata>; fts?: FtsMetadata; geom?: GeomMetadata; page?: any; limit?: any; sort?: any; layout?: any; zoom?: any; bbox?: any; center?: any; card?: any; } /** * Estado simples (da URL parseada) */ interface ParsedState { filters?: Record<string, any>; fts?: string | { value: string; operator?: string; }; geom?: { type: string; [key: string]: any; }; [key: string]: any; } /** * Request enriquecido (para backend) */ interface EnrichedRequest { filters?: Record<string, any>; fts?: { value: string; operator: 'websearch' | 'plainto' | 'phrase' | 'boolean'; }; geom?: { operation: 'within' | 'intersects' | 'near'; geometry: { type: string; [key: string]: any; }; }; [key: string]: any; } /** * Options externas do enricher (separadas do schema) */ interface EnricherOptions { defaults?: { fts?: { operator?: 'websearch' | 'plainto' | 'phrase' | 'boolean'; }; geom?: { operation?: 'within' | 'intersects' | 'near'; }; arrays?: { operator?: 'and' | 'or'; }; ranges?: { operator?: 'between' | 'range'; }; }; globalConfig?: { onChange?: 'submit' | 'default'; debounce?: number; validateOnChange?: boolean; hideDisabledOptions?: boolean; sortOptions?: boolean; cacheConditions?: boolean; }; strict?: boolean; } /** * Configuração do enricher */ interface EnricherConfig { schema: SearchSchema; options?: EnricherOptions; } /** * Schema de campo individual (LEGACY - para backward compatibility) * @deprecated Use FieldMetadata instead */ interface FieldSchema { key: string; type: 'select' | 'range' | 'search' | 'boolean' | 'array'; operator?: 'and' | 'or' | 'equals' | 'contains' | 'between' | 'gte' | 'lte'; multiple?: boolean; default?: any; } /** * 🎯 Search State Enricher - Classe Principal * * Enriquece estado da URL com operadores baseado em schema */ declare class SearchStateEnricher { private schema; private options; /** * Campos que devem ser tratados como string, não array * Importante para validar se AND em campos string faz sentido */ private static readonly STRING_FIELDS; constructor(config: EnricherConfig); /** * Migra schema legado para novo formato * @deprecated Apenas para backward compatibility */ private migrateFromLegacySchema; /** * Enriquece estado simples para request do backend */ enrich(state: ParsedState): EnrichedRequest; /** * Enriquece FTS com operador padrão */ private enrichFts; /** * Enriquece GEOM com operator padrão (CORRIGIDO para API format) */ private enrichGeom; /** * Enriquece FILTERS baseado no schema */ private enrichFilters; /** * Enriquece campo individual baseado no schema */ private enrichField; /** * Enriquece array com operador AND/OR (CORRIGIDO com validação de tipos) */ private enrichArrayField; /** * Enriquece range com operador between/gte/lte */ private enrichRangeField; /** * Enriquece campo simples */ private enrichSimpleField; /** * Busca metadata de um campo específico */ private getFieldSchema; /** * Verifica se valor é um range (objeto com min/max) */ private isRangeValue; } export { Base64Resolver, BaseResolver, BetweenIdentifier, DomainDataDisplayEnricher, type EnrichedRequest, type EnricherConfig, FieldExtractor, type FieldSchema, FieldsResolver, JsonToZodGenerator, LatLngResolver, MinMaxIdentifier, PaginationSortResolver, type ParsedState, PassthroughResolver, RangeIdentifier, type SearchSchema, SearchStateEnricher, SimpleValueResolver, SlugGenerator, UrlStateSerializer, DomainDataDisplayEnricher as default, defaultImoveisConfig, expandArrayFieldToBoolean, formatters, getFieldsByCategory, getFieldsByKeys, isValidSlug, defaultConfig as slugGeneratorDefaultConfig, slugify, sortFields, templateProcessor, truncateSlug, defaultConfig$1 as urlSerializerDefaultConfig, useEnrich, useEnrichList, useEnricher };