UNPKG

@horizon-apps/domain-schema-core

Version:

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

282 lines (231 loc) 9.07 kB
# 🏗️ Plano de Implementação Multi-Search v2.0 ## 📋 **CHECKLIST COMPLETO - NADA FICA DE FORA** ### **🔧 ETAPA 1: Interfaces Base** ✅ COMPLETO - [x] Criar interfaces MultiSearchRequest/Response limpas - [x] Interface GeospatialFilter com bbox/polygon - [x] Interface PrismaMultiQuery para transaction - [x] Validação Zod completa - [x] Fragmentação em arquivo separado: `multi-search-interfaces.ts` ### **🔧 ETAPA 2: Mapper Geoespacial** ✅ COMPLETO - [x] Função extractGeospatialQuery (bbox/polygon → SQL) - [x] Função prismaWhereToSQL (conversão básica) - [x] Fragmentação em arquivo separado: `geospatial-utils.ts` - [x] Teste isolado passando: `geospatial-function.test.ts` ### **🔧 ETAPA 3: Multi Request Mapper** ✅ COMPLETO - [x] Classe MultiSearchMapper completa - [x] Método mapMultiSearch (request → queries) - [x] Método buildListQueries (paginação) - [x] Método buildMapQueries (sem paginação + geo) - [x] Validação completa de entrada - [x] Fragmentação em arquivo separado: `multi-search-mapper.ts` - [x] Teste isolado passando: `multi-search-mapper.test.ts` ### **🔧 ETAPA 4: Service com Transaction** ✅ COMPLETO - [x] Classe PrismaMultiService completa - [x] Método multiSearch com $transaction - [x] Processamento paralelo de queries - [x] Separação automática property/relations - [x] Cálculo de bounds geográficos - [x] Logs de entrada/saída - [x] Fragmentação em arquivo separado: `multi-search-service.ts` - [x] Teste isolado passando: `multi-search-service.test.ts` ### **🔧 ETAPA 5: Integração Completa** ✅ COMPLETO - [x] Teste mapper + service juntos - [x] Cenário bbox (lista + mapa + meta) - [x] Cenário polygon (só mapa) - [x] Validação de erros - [x] Performance com transaction - [x] Teste end-to-end passando: `integration-complete.test.ts` ### **🔧 ETAPA 6: Documentação** ✅ COMPLETO - [x] Documentar implementação realizada - [x] Exemplos de uso completos - [x] Breaking changes documentation ### **🔧 ETAPA 7: Schema Awareness** ✅ COMPLETO - [x] Integrar HorizonSchema no MultiSearchMapper - [x] Expandir schema de teste com geo-point location - [x] Implementar validação de campos vs schema - [x] Adicionar type safety para filtros geoespaciais - [x] Criar testes com schema awareness - [x] Documentar nova funcionalidade ## 🎯 **IMPLEMENTAÇÃO COMPLETA - FUNCIONANDO 100%****TODOS OS TESTES PASSANDO****ARQUITETURA FRAGMENTADA CORRETAMENTE****INTEGRAÇÃO END-TO-END FUNCIONAL** ## 📁 **ESTRUTURA DE ARQUIVOS CRIADA** ``` src/search-request-to-prisma-mapper/ ├── index.ts (arquivo original + exports) ├── multi-search-interfaces.ts (interfaces fragmentadas) ├── multi-search-mapper.ts (mapper novo) ├── geospatial-utils.ts (funções geo) ├── docs/ │ └── readme.md (doc movida) └── tests/ ├── geospatial-function.test.ts (teste geo isolado) ├── multi-search-mapper.test.ts (teste mapper) ├── multi-search-schema-awareness.test.ts (teste schema awareness) ├── index.test.ts (teste original) └── schema-awareness.test.ts (teste mapper original) src/prisma-generic-search-service/ ├── index.ts (arquivo original + exports) ├── multi-search-service.ts (service novo) └── tests/ ├── multi-search-service.test.ts (teste service) ├── integration-complete.test.ts (teste integração) ├── prisma-generic-search-service.test.ts (teste original) └── prisma-logs.test.ts (teste original) ``` ## 🚀 **FORMATO DE USO** ### **Opção 1: Sem Schema (compatibilidade)** ```typescript // 1. Frontend Request (novo formato) const request: MultiSearchRequest = { include: ['list', 'map', 'meta'], list: { fields: ['id', 'title', 'price'], relations: { broker: true }, pagination: { page: 1, limit: 10 } }, map: { fields: ['id', 'latitude', 'longitude'] }, filters: { tipo: { value: 'Casa' }, location: { value: { type: 'bbox', bounds: { west: -51, south: -30, east: -50, north: -29 } } } } } // 2. Mapper: Frontend → Prisma (sem validação) const mapper = MultiSearchMapper.createWithoutSchema() const queries = mapper.mapMultiSearch(request) // 3. Service: Transaction paralela const service = new PrismaMultiService('property', prisma) const result = await service.multiSearch(queries) // 4. Response estruturada console.log(result.list?.data) // Lista paginada console.log(result.map?.data) // Dados do mapa console.log(result.meta) // Metadados globais ``` ### **Opção 2: Com Schema Awareness (recomendado)** ```typescript import { TEST_SCHEMA_WITH_GEO } from './multi-search-interfaces' // 1. Schema de validação const schema = TEST_SCHEMA_WITH_GEO // ou seu próprio schema // 2. Mapper com validação const mapper = MultiSearchMapper.createWithSchema(schema) // 3. Request com validação automática const request: MultiSearchRequest = { include: ['list', 'map'], list: { fields: ['id', 'title', 'tipo'], // ✅ Validados vs schema pagination: { page: 1, limit: 10 } }, map: { fields: ['latitude', 'longitude'] // ✅ Validados vs schema }, filters: { location: { // ✅ Validado vs geo-point no schema value: { type: 'polygon', coordinates: [[-49.76, -29.18], [-50.87, -29.09], [-49.76, -29.18]] } } } } // 4. Execução com type safety const queries = mapper.mapMultiSearch(request) // Valida campos automaticamente const result = await service.multiSearch(queries) ``` ### **Opção 3: Compatibilidade estática (para testes)** ```typescript // Para manter testes existentes funcionando const queries = MultiSearchMapper.mapMultiSearch(request) ``` ## 🚨 **REGRAS CRÍTICAS DE USO** ### **⚠️ SCHEMA É OBRIGATÓRIO PARA ARRAYS** **DESCOBERTA CRÍTICA:** `createSQLBuilder()` **DEVE** receber schema obrigatoriamente para detectar campos array corretamente. #### **❌ ERRO COMUM:** ```typescript // SEM SCHEMA = CAMPOS ARRAY NÃO FUNCIONAM const sqlBuilder = createSQLBuilder() // ❌ SEM SCHEMA! ``` **Resultado:** Campo `operacao` (que é `string[]` no PostgreSQL) é tratado como string simples: ```sql -- SQL INCORRETO gerado: WHERE operacao = 'venda' -- ❌ ERRO! Vai dar "malformed array literal" ``` #### **✅ SOLUÇÃO CORRETA:** ```typescript import { createTestPropertySchema } from './filter/schema-adapter' // ✅ SEMPRE PASSAR SCHEMA const schema = createTestPropertySchema() const sqlBuilder = createSQLBuilder({ schema }) ``` **Resultado:** Campo `operacao` é corretamente detectado como array: ```sql -- SQL CORRETO gerado: WHERE 'venda' = ANY(operacao) -- ✅ FUNCIONA! Detecta array via SSOT ``` #### **🔧 COMO APLICAR:** **1. URL Parser Integration:** ```typescript import { createSQLBuilder } from '../postgre-search-sql-builder' import { createTestPropertySchema } from '../postgre-search-sql-builder/filter/schema-adapter' // 🚨 OBRIGATÓRIO: Schema para detecção de arrays const schema = createTestPropertySchema() const sqlBuilder = createSQLBuilder({ schema }) ``` **2. Examples e Database Testing:** ```typescript // TODOS os examples e testes devem seguir este padrão const schema = createTestPropertySchema() const sqlBuilder = createSQLBuilder({ schema }) // Agora operacao, caracteristicas, tags (arrays) funcionam corretamente ``` #### **🔍 COMO IDENTIFICAR O PROBLEMA:** **Sintomas:** - Erro PostgreSQL: `malformed array literal: "venda"` - SQL gerado: `operacao = 'venda'` em vez de `'venda' = ANY(operacao)` - Filtros de array não funcionam **Diagnóstico:** - Verificar se `createSQLBuilder({ schema })` está sendo usado - Confirmar se schema contém definição `string[]` para campos array **Validação:** ```typescript // Verificar se schema está sendo usado: console.log(sqlBuilder.getStats().hasSchema) // deve ser true ``` ## 🔥 **TROUBLESHOOTING COMUM** ### **Problema: "malformed array literal: 'venda'"** **Causa:** `createSQLBuilder()` chamado sem schema parameter **Sintoma:** ```sql WHERE operacao = 'venda' -- Tenta inserir string em campo array ``` **Solução:** ```typescript // ❌ ERRADO: const sqlBuilder = createSQLBuilder() // ✅ CORRETO: const schema = createTestPropertySchema() const sqlBuilder = createSQLBuilder({ schema }) ``` ### **Problema: Arrays sendo tratados como strings** **Causa:** FilterConverter sem informação SSOT sobre tipos de campo **Diagnóstico:** ```typescript // Verificar se campo está definido como array no schema: const fieldInfo = schema.fields.find(f => f.name === 'operacao') console.log(fieldInfo?.type) // deve ser 'string[]' ``` **Solução:** Garantir que schema define corretamente: ```typescript { name: 'operacao', type: 'string[]', // ✅ CRÍTICO: [] indica array db: 'operacao' } ```