diff --git a/src/tipoFiltro.26.ts b/src/tipoFiltro.26.ts new file mode 100644 index 0000000..7313f03 --- /dev/null +++ b/src/tipoFiltro.26.ts @@ -0,0 +1,207 @@ +/** + * ============================================================================= + * tipoFiltro26 + * ============================================================================= + * + * OBJETIVO + * ----------------------------------------------------------------------------- + * Gerar automaticamente a tipagem de filtros compatíveis com operadores + * padrão do PostgreSQL, a partir de um tipo base T. + * + * Este tipo foi projetado para: + * - Construção de filtros dinâmicos + * - Geração posterior de WHERE (Knex / SQL) + * - Uso seguro por IA (evita filtros inválidos em nível de tipo) + * + * + * FORMATO DO FILTRO + * ----------------------------------------------------------------------------- + * 1) Campos simples: + * + * { + * idade: { ">=": 18 } + * } + * + * 2) Campos aninhados: + * + * { + * carro: { + * ano: { "=": 2020 } + * } + * } + * + * 3) Operador E (AND): + * + * { + * E: [ + * { idade: { ">=": 18 } }, + * { nome: { like: "%pa%" } } + * ] + * } + * + * 4) Operador OU (OR): + * + * { + * OU: [ + * { idade: { "<": 18 } }, + * { idade: { ">=": 60 } } + * ] + * } + * + * 5) Combinação complexa: + * + * { + * idade: { ">=": 18 }, + * OU: [ + * { nome: { like: "%pa%" } }, + * { + * E: [ + * { carro: { ano: { "=": 2020 } } }, + * { carro: { modelo: { in: ["Civic"] } } } + * ] + * } + * ] + * } + * + * + * REGRAS IMPORTANTES (PARA IA) + * ----------------------------------------------------------------------------- + * - Apenas campos existentes em T podem ser usados. + * - Operadores são restritos por tipo do campo. + * - Objetos são tratados recursivamente. + * - Arrays NÃO são tratados como objeto recursivo. + * - Funções NÃO são consideradas campos filtráveis. + * + * + * OPERADORES SUPORTADOS + * ----------------------------------------------------------------------------- + * number: + * =, !=, >, >=, <, <=, in + * + * string: + * =, !=, like, in + * + * boolean: + * =, !=, in + * + * Não há suporte automático a: + * - null + * - date + * - jsonb + * - arrays + * + * Essas extensões devem ser adicionadas explicitamente. + * + * ============================================================================= + */ + + +/* ============================================================================= + OPERADORES POSTGRESQL POR TIPO +============================================================================= */ + +type PgOpsNumber = { + "="?: number + "!="?: number + ">"?: number + ">="?: number + "<"?: number + "<="?: number + in?: number[] +} + +type PgOpsString = { + "="?: string + "!="?: string + like?: string + in?: string[] +} + +type PgOpsBoolean = { + "="?: boolean + "!="?: boolean + in?: boolean[] +} + + +/* ============================================================================= + SELEÇÃO AUTOMÁTICA DE OPERADORES BASEADA NO TIPO DO CAMPO +============================================================================= */ + +type PgOpsFor = + V extends number ? PgOpsNumber : + V extends string ? PgOpsString : + V extends boolean ? PgOpsBoolean : + never + + +/* ============================================================================= + UTILITÁRIO: DETECTAR OBJETO PLANO +============================================================================= */ + +type IsPlainObject = + T extends object + ? T extends Function ? false + : T extends readonly any[] ? false + : true + : false + + +/* ============================================================================= + FILTRO RECURSIVO POR CAMPOS +============================================================================= */ + +type FiltroCampos = { + [K in keyof T]?: IsPlainObject extends true + ? tipoFiltro26 + : PgOpsFor +} + + +/* ============================================================================= + TIPO PRINCIPAL EXPORTADO +============================================================================= */ + +export type tipoFiltro26 = FiltroCampos & { + /** + * E => AND lógico + * Todos os filtros dentro do array devem ser verdadeiros. + */ + E?: tipoFiltro26[] + + /** + * OU => OR lógico + * Pelo menos um filtro dentro do array deve ser verdadeiro. + */ + OU?: tipoFiltro26[] +} + + + +/* ============================================================================= + EXEMPLO DE USO +============================================================================= */ + +type Pessoa = { + codigo: string + nome: string + idade: number + carro: { + modelo: string + ano: number + } +} + +const _filtro: tipoFiltro26 = { + idade: { ">=": 18 }, + + OU: [ + { nome: { like: "%pa%" } }, + { + E: [ + { carro: { ano: { "=": 2020 } } }, + { carro: { modelo: { in: ["Civic", "Corolla"] } } }, + ], + }, + ], +}