.
This commit is contained in:
parent
303832ba8c
commit
92300c8e3b
1 changed files with 207 additions and 0 deletions
207
src/tipoFiltro.26.ts
Normal file
207
src/tipoFiltro.26.ts
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/**
|
||||
* =============================================================================
|
||||
* tipoFiltro26<T>
|
||||
* =============================================================================
|
||||
*
|
||||
* 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> =
|
||||
V extends number ? PgOpsNumber :
|
||||
V extends string ? PgOpsString :
|
||||
V extends boolean ? PgOpsBoolean :
|
||||
never
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
UTILITÁRIO: DETECTAR OBJETO PLANO
|
||||
============================================================================= */
|
||||
|
||||
type IsPlainObject<T> =
|
||||
T extends object
|
||||
? T extends Function ? false
|
||||
: T extends readonly any[] ? false
|
||||
: true
|
||||
: false
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
FILTRO RECURSIVO POR CAMPOS
|
||||
============================================================================= */
|
||||
|
||||
type FiltroCampos<T> = {
|
||||
[K in keyof T]?: IsPlainObject<T[K]> extends true
|
||||
? tipoFiltro26<T[K]>
|
||||
: PgOpsFor<T[K]>
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
TIPO PRINCIPAL EXPORTADO
|
||||
============================================================================= */
|
||||
|
||||
export type tipoFiltro26<T> = FiltroCampos<T> & {
|
||||
/**
|
||||
* E => AND lógico
|
||||
* Todos os filtros dentro do array devem ser verdadeiros.
|
||||
*/
|
||||
E?: tipoFiltro26<T>[]
|
||||
|
||||
/**
|
||||
* OU => OR lógico
|
||||
* Pelo menos um filtro dentro do array deve ser verdadeiro.
|
||||
*/
|
||||
OU?: tipoFiltro26<T>[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
EXEMPLO DE USO
|
||||
============================================================================= */
|
||||
|
||||
type Pessoa = {
|
||||
codigo: string
|
||||
nome: string
|
||||
idade: number
|
||||
carro: {
|
||||
modelo: string
|
||||
ano: number
|
||||
}
|
||||
}
|
||||
|
||||
const _filtro: tipoFiltro26<Pessoa> = {
|
||||
idade: { ">=": 18 },
|
||||
|
||||
OU: [
|
||||
{ nome: { like: "%pa%" } },
|
||||
{
|
||||
E: [
|
||||
{ carro: { ano: { "=": 2020 } } },
|
||||
{ carro: { modelo: { in: ["Civic", "Corolla"] } } },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue