npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@horizon-modules/property-model-v3

v3.6.0

Published

Modelo de propriedades imobiliárias v3 - Sistema de atributos dinâmicos

Readme

@horizon-modules/property-model-v3

Sistema completo para modelagem de propriedades imobiliárias V3 com atributos dinâmicos, validação Zod, profiling de dados e pipeline de desenvolvimento automatizado.

📦 Instalação

npm install @horizon-modules/property-model-v3
# ou
pnpm add @horizon-modules/property-model-v3

🚀 Uso Básico

import { 
  PropertyModel,
  PropertyModelSchema,
  validatePropertyModel,
  safeValidatePropertyModel,
  generateFakeProperty,
  PropertyModelJsonSchema
} from '@horizon-modules/property-model-v3';

// Exemplo de propriedade V3
const property: PropertyModel = {
  reference: "AP001_V3",
  title: "Apartamento Premium - 3 qtos, 150m²",
  description: "Apartamento moderno com acabamentos de primeira linha...",
  attributes: {
    tipo: "Apartamento",
    operacao: ["venda"],
    dormitorios: 3,
    banheiros: 2,
    area_util: 150,
    valor_venda: 850000,
    endereco_cidade: "São Paulo",
    endereco_bairro: "Vila Madalena"
  },
  media_assets: {
    images: [
      {
        full: "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80",
        cover: true
      }
    ]
  },
  settings: {
    currency_unit: "BRL",
    area_unit: "m2",
    exibir_no_mapa: true
  }
};

// Validação com Zod
const validProperty = validatePropertyModel(property);

// Validação safe (nunca lança erro)
const result = safeValidatePropertyModel(property);
if (result.success) {
  console.log("Propriedade válida:", result.data);
} else {
  console.log("Erros:", result.error.issues);
}

// Gerar dados fake
const fakeProperty = generateFakeProperty("apartamento");

🏗️ Arquitetura PropertyModel V3

Estrutura Principal

interface PropertyModel {
  reference: string              // Código único
  title: string                 // Título da propriedade
  description: string           // Descrição detalhada
  attributes: Record<string, any>  // Atributos dinâmicos
  media_assets: MediaAssets     // Fotos, vídeos, tours
  settings?: SettingsFormat     // Configurações de formato
  updated_at?: string          // Data de atualização
}

Sistema de Atributos Dinâmicos

O V3 substitui o array de atributos por um objeto chave-valor mais flexível:

// V2 (antigo)
attributes: [
  { key: "dormitorios", value: 3 },
  { key: "valor_venda", value: 850000, unit: "BRL" }
]

// V3 (novo)  
attributes: {
  dormitorios: 3,
  valor_venda: 850000,
  endereco_cidade: "São Paulo",
  caracteristicas: ["Churrasqueira", "Piscina"]
}

Benefícios do V3:

  • ✅ Acesso direto: property.attributes.dormitorios
  • ✅ Menos verboso e mais legível
  • ✅ Melhor performance em consultas
  • ✅ Compatível com NoSQL (MongoDB, DynamoDB)
  • ✅ Validação Zod nativa

Media Assets

interface MediaAssets {
  images?: ImageMedia[]         // Fotos do imóvel
  videos?: VideoMedia[]         // Vídeos (YouTube, Vimeo)
  virtual_tours?: VirtualTourMedia[]  // Tours 360°
  documents?: DocumentMedia[]   // PDFs, documentos
}

interface ImageMedia {
  full: string                  // URL da imagem completa
  md?: string                  // Versão 640x480
  sm?: string                  // Versão 320x240  
  cover?: boolean              // Se é imagem principal
}

🎨 Gerador de Dados Fake Avançado

Sistema baseado em profiling de dados reais do Arbo CRM com 20+ atributos por imóvel:

import { 
  generateFakeProperty,
  generateFakeProperties,
  generateFakePropertyByType,
  getAvailablePropertyTypes 
} from '@horizon-modules/property-model-v3';

// Gerar uma propriedade aleatória
const property = generateFakeProperty();

// Gerar 50 propriedades  
const properties = generateFakeProperties(50);

// Gerar tipo específico
const apartamento = generateFakePropertyByType("apartamento");
const casa = generateFakePropertyByType("casa");
const terreno = generateFakePropertyByType("terreno");

// Ver tipos disponíveis
console.log(getAvailablePropertyTypes());
// ["apartamento", "casa", "sobrado", "terreno", "comercial"]

Características dos Dados Fake

  • 📍 Localização brasileira: 5 cidades + bairros reais
  • 💰 Valores realistas: Baseados em dados reais do Arbo CRM
  • 🏠 Atributos contextuais: 20-30 atributos por tipo de imóvel
  • 🖼️ Imagens Unsplash: URLs funcionais categorizadas por tipo
  • ⚡ Performance: Baseado em profiling estatístico

Exemplo de Propriedade Fake Gerada

{
  "reference": "FAKE_APARTAMENTOS_001", 
  "title": "Apartamento Premium - 3 qtos, 150m², 3 vagas",
  "description": "Apartamento moderno com acabamentos de primeira linha...",
  "attributes": {
    "tipo": "Apartamento",
    "operacao": ["venda"],
    "dormitorios": 3,
    "banheiros": 2,
    "suites": 1,
    "vagas": 3,
    "area_util": 150,
    "area_total": 180,
    "valor_venda": 1200000,
    "valor_condominio": 800,
    "andar": 12,
    "endereco_cidade": "São Paulo",
    "endereco_estado": "SP", 
    "endereco_bairro": "Vila Madalena",
    "endereco_cep": "05414-000",
    "caracteristicas": ["Churrasqueira", "Piscina", "Academia"],
    "mobiliado": false,
    "aceita_pets": true,
    "portao_eletronico": true
  },
  "media_assets": {
    "images": [
      {
        "full": "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80",
        "cover": true
      }
    ]
  }
}

📊 ProfilerService - Análise de Dados

Ferramenta para análise estatística de datasets PropertyModel:

import { ProfilerService, profileProperties } from '@horizon-modules/property-model-v3';

// Análise de arquivos
const profiler = new ProfilerService({
  inputDir: './data/properties',
  outputDir: './output',
  fieldConfigs: {
    'attributes.endereco_cidade': { maxExamples: 50 },
    'attributes.caracteristicas': { maxExamples: 100 }
  }
});

const report = await profiler.profile();
console.log(report);
// {
//   "attributes.tipo": ["Casa", "Apartamento", "Terreno"],
//   "attributes.endereco_cidade": ["São Paulo", "Rio de Janeiro", ...],
//   "attributes.caracteristicas": ["Churrasqueira", "Piscina", ...]
// }

// Análise em memória
const inMemoryReport = await profileProperties(propertyArray);

Características:

  • Concatena arrays: Arrays de strings viram lista única de valores
  • Objetos aninhados: Analisa attributes.endereco_cidade
  • Configurável: Controle de quantos exemplos por campo
  • Genérico: Funciona com qualquer estrutura JSON

🎨 Property Customizer - Transformação Baseada em Regras

Sistema para aplicar transformações complexas em dados PropertyV3 através de regras declarativas:

import { 
  PropertyCustomizer,
  type MapRules 
} from '@horizon-modules/property-model-v3';

// Definir regras de transformação
const mapRules: MapRules = {
  attributesRules: [
    {
      key: 'tipo',
      condition: { eq: 'Casa de Condomínio' },
      rules: [
        { fn: 'upsertAttr', key: 'tipo', value: 'Casa/Sobrado' },
        { fn: 'upsertAttr', key: 'subtipo', value: 'Casa' },
        { fn: 'addToArray', key: 'tags', value: 'em-condominio' }
      ]
    },
    {
      key: 'caracteristicas',
      condition: { has_any: ['Piscina'] },
      rules: [
        { fn: 'removeFromArray', key: 'caracteristicas', value: 'Piscina' },
        { fn: 'upsertAttr', key: 'piscina', value: true }
      ]
    }
  ]
};

// Aplicar transformações
const transformedProperty = PropertyCustomizer(property, mapRules);

Actions Disponíveis

  • upsertAttr: Criar/atualizar atributo
  • removeAttr: Remover atributo
  • addToArray: Adicionar valores a array
  • removeFromArray: Remover valores de array

Condições Suportadas

  • Igualdade: eq, not_eq
  • Arrays: has, has_any, not_has
  • Numéricos: gt, gte, lt, lte
  • Texto: contains, starts_with, ends_with
  • Booleanos: is_true, is_false
  • Existência: exists, not_exists

Tags na Description

O sistema processa automaticamente tags especiais na description:

const property = {
  description: `Casa linda [[description-en]]Beautiful house[[/description-en]] 
[[custom-attributes]]
{
  "energia_solar": true,
  "classificacao": "A+"
}
[[/custom-attributes]]
Com vista para o mar`
};

// Após processamento:
// property.attributes.description_en = 'Beautiful house'
// property.attributes.energia_solar = true
// property.description = 'Casa linda Com vista para o mar'

🌐 ApiClientService - Cliente HTTP

Cliente para envio de dados PropertyModel para APIs externas:

import { ApiClientService } from '@horizon-modules/property-model-v3';

const client = new ApiClientService({
  endpoint: 'https://api.imobiliaria.com/properties',
  headers: { 'Authorization': 'Bearer token' },
  batchSize: 10  // Processa 10 por vez
});

// Enviar uma propriedade
await client.sendProperty(property);

// Enviar múltiplas propriedades
await client.sendProperties([prop1, prop2, prop3]);

// Enviar de pasta com JSONs
await client.sendPropertiesFromDir('./data/fake-properties');

Formatos suportados:

  • Array direto: [prop1, prop2]
  • Formato data: { "data": [prop1, prop2] }
  • Categorizado: { "apartamentos": [prop1], "casas": [prop2] }

🔒 Validação com Zod

Sistema robusto de validação em runtime:

import { 
  PropertyModelSchema,
  validatePropertyModel,
  safeValidatePropertyModel 
} from '@horizon-modules/property-model-v3';

// Validação direta (lança erro se inválido)
const property = validatePropertyModel(unknownData);

// Validação safe (nunca lança erro)
const result = safeValidatePropertyModel(unknownData);
if (result.success) {
  console.log("✅ Válido:", result.data);
} else {
  console.log("❌ Erros:", result.error.issues);
}

// Schema customizado
const StrictSchema = PropertyModelSchema.extend({
  reference: z.string().min(5).max(20)
});

📋 JSON Schema Export

Schemas JSON para validação externa:

import { 
  PropertyModelJsonSchema,
  PropertyTypeSchemaJson 
} from '@horizon-modules/property-model-v3';

// Usar com validadores JSON Schema
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(PropertyModelJsonSchema);

const isValid = validate(propertyData);
if (!isValid) {
  console.log(validate.errors);
}

🛠️ Scripts de Desenvolvimento

Pipeline completo para desenvolvimento de dados:

Scripts Principais

# Baixar dados reais do Arbo CRM
npm run dev:download

# Baixar dados fake do pacote arbo-crm  
npm run dev:download-arbo-fake

# Converter dados Arbo para PropertyModel V3
npm run dev:convert

# Fazer profiling dos dados convertidos
npm run dev:profile

# Gerar dados fake baseados no profiling
npm run dev:fake

# Gerar mocks para testes
npm run dev:mocks

# Gerar JSON Schema
npm run dev:json-schema

# Testar JSON Schema
npm run dev:test-json-schema

# Pipeline completo
npm run dev:all

Estrutura de Desenvolvimento

__dev__/
├── data/                           # Dados temporários (não commitados)
│   ├── arbo-downloads/            # Dados reais do Arbo CRM
│   ├── arbo-fake-data-output/     # Dados fake do arbo-crm package
│   ├── property-v3-converted/     # Dados convertidos para V3
│   ├── property-v3-profiling/     # Relatórios de profiling
│   ├── property-v3-fake-data-output/  # Dados fake gerados
│   ├── property-v3-mock-output/   # Mocks para testes
│   └── json-schema/               # JSON Schema gerado
├── scripts/                       # Scripts de desenvolvimento
│   ├── arbo-download-properties.ts    # Baixa dados do Arbo
│   ├── arbo-download-fake-data.ts     # Baixa fake data do arbo-crm
│   ├── arbo-convert-to-property-v3.ts # Converte para V3
│   ├── profile-properties.ts          # Faz profiling
│   ├── generate-fake-data.ts          # Gera dados fake
│   ├── generate-mocks.ts              # Gera mocks
│   ├── generate-json-schema.ts        # Gera JSON Schema
│   └── test-json-schema.ts            # Testa JSON Schema
├── services/                      # Serviços de desenvolvimento
│   └── MockGeneratorService.ts        # Gerador de mocks
└── tests/                         # Testes dos serviços dev
    └── MockGeneratorService.test.ts

Fluxo de Desenvolvimento

  1. 🔄 Download: dev:download → Baixa dados reais do Arbo CRM
  2. 📊 Profiling: dev:profile → Analisa padrões estatísticos nos dados
  3. 🎨 Fake Data: dev:fake → Gera dados fake baseados no profiling
  4. 🧪 Mocks: dev:mocks → Gera mocks para testes unitários
  5. 📋 Schema: dev:json-schema → Gera JSON Schema para validação externa

🏠 Modelo de Atributos

Sistema com 96 atributos pré-definidos em 8 categorias:

import { PropertyAttributesModel } from '@horizon-modules/property-model-v3';

// Ver todos os atributos disponíveis
console.log(PropertyAttributesModel.length); // 96

// Atributos por categoria
const comerciais = PropertyAttributesModel.filter(attr => attr.cat === "comercial");
const valores = PropertyAttributesModel.filter(attr => attr.cat === "valores");
const dependencias = PropertyAttributesModel.filter(attr => attr.cat === "dependencias");

// Buscar atributo específico
const dormitorios = PropertyAttributesModel.find(attr => attr.key === "dormitorios");
console.log(dormitorios);
// { key: "dormitorios", label: "Dormitórios", type: "Number", cat: "dependencias" }

Categorias de Atributos

  1. comercial (8): operacao, status_comercial, financiavel, aceita_permuta
  2. valores (12): valor_venda, valor_locacao, valor_condominio, valor_iptu
  3. situacoes (6): disponivel, reservado, vendido, alugado
  4. localizacao (15): endereco_cidade, endereco_bairro, latitude, longitude
  5. estrutura (20): tipo, subtipo, area_total, area_util, conservacao
  6. dependencias (8): dormitorios, banheiros, suites, vagas
  7. caracteristicas (15): mobiliado, aceita_pets, churrasqueira, piscina
  8. corretor (12): corretor_nome, corretor_telefone, corretor_email

🔧 Utilitários

import { 
  verifyAttrKeyInPropertyV3Model,
  mergePropertyAttributesModel,
  sortAttributes,
  preparaAttrValueLabel,
  unitListModel,
  formatListModel
} from '@horizon-modules/property-model-v3';

// Verificar se atributo existe
const attr = verifyAttrKeyInPropertyV3Model("dormitorios");

// Mesclar modelos de atributos
const customModel = mergePropertyAttributesModel(
  PropertyAttributesModel,
  [{ key: "piscina", label: "Piscina", type: "Boolean" }]
);

// Formatar labels de arrays
preparaAttrValueLabel(["venda", "locacao"]);
// Retorna: "venda e locacao"

// Unidades disponíveis
console.log(unitListModel.currency); // [{ key: "BRL", label: "R$" }]
console.log(unitListModel.area);     // [{ key: "m2", label: "m²" }]

🧪 Testes

# Executar todos os testes
npm run test

# Testes com cobertura
npm run test:coverage

# Testes dos serviços de desenvolvimento
npm run dev:test

# Verificação de tipos
npm run typecheck

# Build
npm run build

📈 Exemplo Completo

import { 
  generateFakeProperties,
  ProfilerService,
  ApiClientService,
  validatePropertyModel
} from '@horizon-modules/property-model-v3';

async function exemploCompleto() {
  // 1. Gerar 100 propriedades fake
  console.log('🎨 Gerando dados fake...');
  const properties = generateFakeProperties(100);
  
  // 2. Validar todas as propriedades
  console.log('🔍 Validando propriedades...');
  const validProperties = properties.filter(prop => {
    try {
      validatePropertyModel(prop);
      return true;
    } catch {
      return false;
    }
  });
  
  console.log(`✅ ${validProperties.length}/${properties.length} propriedades válidas`);
  
  // 3. Fazer profiling dos dados
  console.log('📊 Fazendo profiling...');
  const profiler = new ProfilerService({ inputData: validProperties });
  const report = await profiler.profile();
  
  console.log('Tipos encontrados:', report['attributes.tipo']);
  console.log('Cidades encontradas:', report['attributes.endereco_cidade']);
  
  // 4. Enviar para API (exemplo)
  const client = new ApiClientService({
    endpoint: 'https://api.exemplo.com/properties',
    batchSize: 5
  });
  
  console.log('🚀 Enviando para API...');
  await client.sendProperties(validProperties.slice(0, 10));
  
  console.log('🎉 Processo concluído!');
}

exemploCompleto().catch(console.error);

🚀 Integração com Arbo CRM

O projeto integra nativamente com o @horizon-modules/arbo-crm-integration:

// Os scripts de desenvolvimento usam o arbo-crm-integration
// para baixar dados reais e convertê-los para PropertyModel V3

// Dados reais → Profiling → Fake data realista
// Este processo garante que os dados fake sejam baseados
// em dados reais do mercado imobiliário brasileiro

📦 Exports Principais

// Modelos e Tipos
export type { PropertyModel, MediaAssets, SettingsFormat }

// Schemas Zod
export { PropertyModelSchema, validatePropertyModel, safeValidatePropertyModel }

// JSON Schemas
export { PropertyModelJsonSchema, PropertyTypeSchemaJson }

// Gerador de Dados Fake
export { generateFakeProperty, generateFakeProperties, generateFakePropertyByType }

// Serviços
export { ProfilerService, ApiClientService }

// Property Customizer
export { PropertyCustomizer }
export type { PropertyV3, MapRules, AttributeRule, CustomAction }

// Modelo de Atributos
export { PropertyAttributesModel, unitListModel, formatListModel }

// Utilitários
export { verifyAttrKeyInPropertyV3Model, mergePropertyAttributesModel, sortAttributes }

🔄 Migração do V2 para V3

Principais Mudanças

  1. Atributos: Array → Objeto chave-valor
  2. Media: mediamedia_assets com estrutura tipada
  3. Validação: Zod schemas obrigatórios
  4. Settings: Novo campo para configurações de formato

Exemplo de Migração

// V2
const propertyV2 = {
  reference: "AP001",
  attributes: [
    { key: "dormitorios", value: 3 },
    { key: "valor_venda", value: 850000, unit: "BRL" }
  ],
  media: {
    pictures: ["foto1.jpg", "foto2.jpg"]
  }
};

// V3
const propertyV3 = {
  reference: "AP001", 
  title: "Apartamento 3 dormitórios",
  description: "Descrição do imóvel...",
  attributes: {
    dormitorios: 3,
    valor_venda: 850000
  },
  media_assets: {
    images: [
      { full: "foto1.jpg", cover: true },
      { full: "foto2.jpg", cover: false }
    ]
  },
  settings: {
    currency_unit: "BRL",
    area_unit: "m2"
  }
};

📄 Licença

MIT - veja LICENSE para detalhes.

Desenvolvido pela Horizon Modules 🏗️