merge
This commit is contained in:
commit
95ceb92d9c
59 changed files with 1114 additions and 452 deletions
0
src/aleatorio.ts
Normal file → Executable file
0
src/aleatorio.ts
Normal file → Executable file
0
src/cacheMemoria.ts
Normal file → Executable file
0
src/cacheMemoria.ts
Normal file → Executable file
0
src/constantes.ts
Normal file → Executable file
0
src/constantes.ts
Normal file → Executable file
0
src/consulta.ts
Normal file → Executable file
0
src/consulta.ts
Normal file → Executable file
27
src/dayjs.ts
27
src/dayjs.ts
|
|
@ -1,27 +0,0 @@
|
|||
import dayjs, { type Dayjs } from "dayjs"
|
||||
|
||||
export type { ManipulateType } from "dayjs"
|
||||
|
||||
import duration from "dayjs/plugin/duration.js"
|
||||
import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js"
|
||||
import isSameOrBefore from "dayjs/plugin/isSameOrBefore.js"
|
||||
import minMax from "dayjs/plugin/minMax.js"
|
||||
import relativeTime from "dayjs/plugin/relativeTime.js"
|
||||
import timezone from "dayjs/plugin/timezone.js"
|
||||
import utc from "dayjs/plugin/utc.js"
|
||||
import weekOfYear from "dayjs/plugin/weekOfYear.js"
|
||||
import "dayjs/locale/pt-br.js"
|
||||
dayjs.locale("pt-br")
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(weekOfYear)
|
||||
dayjs.extend(isSameOrBefore)
|
||||
dayjs.extend(isSameOrAfter)
|
||||
dayjs.extend(minMax)
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(duration)
|
||||
|
||||
export const dayjsbr = dayjs
|
||||
|
||||
export type { Dayjs }
|
||||
107
src/dayjs26.ts
Executable file
107
src/dayjs26.ts
Executable file
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Utilitário de configuração do Dayjs focado em compatibilidade com SSR.
|
||||
*
|
||||
* PROBLEMA:
|
||||
* A importação direta do `dayjs` e seus plugins frequentemente causa conflitos em ambientes
|
||||
* de Renderização do Lado do Servidor (SSR), como Nuxt ou Next.js, devido a discrepâncias
|
||||
* na resolução de módulos (ESM vs CJS) e instabilidades de importação.
|
||||
*
|
||||
* SOLUÇÃO:
|
||||
* Este módulo utiliza o padrão de Injeção de Dependência. Ele expõe apenas tipagens e
|
||||
* uma função de configuração (`defineDayjsBr`). A responsabilidade de importar as
|
||||
* bibliotecas "vivas" é delegada à aplicação consumidora (o cliente da função).
|
||||
*
|
||||
* Isso permite que o bundler da aplicação principal (Vite, Webpack, etc.) gerencie as
|
||||
* instâncias, garantindo consistência e evitando erros de "module not found" ou
|
||||
* instâncias duplicadas/não inicializadas adequadamente.
|
||||
*/
|
||||
|
||||
import type _dayjs from "dayjs"
|
||||
import type { Dayjs } from "dayjs"
|
||||
|
||||
export type { ManipulateType } from "dayjs"
|
||||
|
||||
// Importação apenas de TIPOS para evitar bundling indesejado neste arquivo
|
||||
import type _duration from "dayjs/plugin/duration"
|
||||
import type _isSameOrAfter from "dayjs/plugin/isSameOrAfter"
|
||||
import type _isSameOrBefore from "dayjs/plugin/isSameOrBefore"
|
||||
import type _minMax from "dayjs/plugin/minMax"
|
||||
import type _relativeTime from "dayjs/plugin/relativeTime"
|
||||
import type _timezone from "dayjs/plugin/timezone"
|
||||
import type _utc from "dayjs/plugin/utc"
|
||||
import type _weekOfYear from "dayjs/plugin/weekOfYear"
|
||||
|
||||
/**
|
||||
* Inicializa e configura o Dayjs com o locale 'pt-br' e plugins essenciais.
|
||||
*
|
||||
* MODO DE USO:
|
||||
* Importe os pacotes reais na sua aplicação e passe-os para esta função.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Em seu arquivo de configuração (ex: plugins/dayjs.ts):
|
||||
* import dayjs from "dayjs"
|
||||
* import duration from "dayjs/plugin/duration"
|
||||
* import isSameOrAfter from "dayjs/plugin/isSameOrAfter"
|
||||
* import isSameOrBefore from "dayjs/plugin/isSameOrBefore"
|
||||
* import minMax from "dayjs/plugin/minMax"
|
||||
* import relativeTime from "dayjs/plugin/relativeTime"
|
||||
* import timezone from "dayjs/plugin/timezone"
|
||||
* import utc from "dayjs/plugin/utc"
|
||||
* import weekOfYear from "dayjs/plugin/weekOfYear"
|
||||
* import { defineDayjsBr } from "p-comuns"
|
||||
* import "dayjs/locale/pt-br" // Importante: importar o locale!
|
||||
|
||||
* export const dayjsbr = defineDayjsBr({
|
||||
* dayjs,
|
||||
* duration,
|
||||
* isSameOrAfter,
|
||||
* isSameOrBefore,
|
||||
* minMax,
|
||||
* relativeTime,
|
||||
* timezone,
|
||||
* utc,
|
||||
* weekOfYear,
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
const defineDayjsBr = ({
|
||||
dayjs,
|
||||
duration,
|
||||
isSameOrAfter,
|
||||
isSameOrBefore,
|
||||
minMax,
|
||||
relativeTime,
|
||||
timezone,
|
||||
utc,
|
||||
weekOfYear,
|
||||
}: {
|
||||
dayjs: typeof _dayjs
|
||||
duration: typeof _duration
|
||||
isSameOrAfter: typeof _isSameOrAfter
|
||||
isSameOrBefore: typeof _isSameOrBefore
|
||||
minMax: typeof _minMax
|
||||
relativeTime: typeof _relativeTime
|
||||
timezone: typeof _timezone
|
||||
utc: typeof _utc
|
||||
weekOfYear: typeof _weekOfYear
|
||||
}) => {
|
||||
// Extensão da biblioteca com os plugins fornecidos
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(weekOfYear)
|
||||
dayjs.extend(isSameOrBefore)
|
||||
dayjs.extend(isSameOrAfter)
|
||||
dayjs.extend(minMax)
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(duration)
|
||||
|
||||
// Definição do locale global
|
||||
dayjs.locale("pt-br")
|
||||
|
||||
return dayjs
|
||||
}
|
||||
|
||||
export { defineDayjsBr }
|
||||
|
||||
export type { Dayjs }
|
||||
0
src/ecosistema/index.ts
Normal file → Executable file
0
src/ecosistema/index.ts
Normal file → Executable file
0
src/ecosistema/urls.ts
Normal file → Executable file
0
src/ecosistema/urls.ts
Normal file → Executable file
0
src/extensoes.ts
Normal file → Executable file
0
src/extensoes.ts
Normal file → Executable file
12
src/graficosPilao.ts
Executable file
12
src/graficosPilao.ts
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
export const graficos_pilao: {
|
||||
[k: string]: { grafico: string; titulo: string }
|
||||
} = {
|
||||
Condicionantes: {
|
||||
grafico: "condicionantes-criadas",
|
||||
titulo: "Condicionantes Criadas",
|
||||
},
|
||||
Licenças: {
|
||||
grafico: "licencas-criadas",
|
||||
titulo: "Licenças Criadas",
|
||||
},
|
||||
}
|
||||
6
src/index.ts
Normal file → Executable file
6
src/index.ts
Normal file → Executable file
|
|
@ -3,19 +3,19 @@ export * from "./auditoria"
|
|||
export * from "./cacheMemoria"
|
||||
export * from "./constantes"
|
||||
export * from "./consulta"
|
||||
export * from "./dayjs"
|
||||
export * from "./dayjs26"
|
||||
export * from "./ecosistema"
|
||||
export * from "./extensoes"
|
||||
export * from "./extensoes"
|
||||
export * from "./local"
|
||||
export * from "./logger"
|
||||
export * from "./logger"
|
||||
export * from "./postgres"
|
||||
export * from "./produtos"
|
||||
export * from "./situacoes"
|
||||
export * from "./testes-de-variaveis"
|
||||
export * from "./texto_busca"
|
||||
export * from "./tipagemRotas"
|
||||
export * from "./tipagemRotas"
|
||||
export * from "./tipoFiltro.26"
|
||||
export * from "./unidades_medida"
|
||||
export * from "./uuid"
|
||||
export * from "./variaveisComuns"
|
||||
|
|
|
|||
0
src/instalarAmbiente.ts
Normal file → Executable file
0
src/instalarAmbiente.ts
Normal file → Executable file
4
src/local/index.ts
Normal file → Executable file
4
src/local/index.ts
Normal file → Executable file
|
|
@ -6,8 +6,8 @@ export const localValor = <T>(
|
|||
chave_: string | any,
|
||||
valor?: T | null,
|
||||
): T | null => {
|
||||
const localStorage = globalThis.localStorage
|
||||
|
||||
const localStorage =
|
||||
"localStorage" in globalThis ? (globalThis as any).localStorage : undefined
|
||||
if (typeof localStorage == "undefined") return null
|
||||
|
||||
const chave =
|
||||
|
|
|
|||
126
src/logger.ts
126
src/logger.ts
|
|
@ -1,126 +0,0 @@
|
|||
import crossFetch from "cross-fetch"
|
||||
import { nomeVariavel } from "./variaveisComuns"
|
||||
|
||||
const LOKI_BASE_URL = "https://log.idz.one"
|
||||
const LOKI_ENDPOINT = "/loki/api/v1/push"
|
||||
export type tipoLokiObjeto = {
|
||||
streams: {
|
||||
stream: {
|
||||
[k: string]: string
|
||||
}
|
||||
values: [string, string][]
|
||||
}[]
|
||||
}
|
||||
|
||||
export const postLogger = async ({
|
||||
objeto,
|
||||
}: {
|
||||
objeto: tipoLokiObjeto
|
||||
}): Promise<[objeto: tipoLokiObjeto, erro?: string]> => {
|
||||
const response = await crossFetch(`${LOKI_BASE_URL}${LOKI_ENDPOINT}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(objeto),
|
||||
}).catch((a) => a)
|
||||
if (!response.ok) {
|
||||
return [objeto, `Erro ${response.status}: ${await response?.text?.()}`]
|
||||
}
|
||||
return [objeto]
|
||||
}
|
||||
|
||||
let cwd = ""
|
||||
|
||||
/** define a localização da pasta do projeto */
|
||||
export const defineCwd = (novoCwd: string) => {
|
||||
cwd = novoCwd
|
||||
}
|
||||
|
||||
type tipoLevel = "info" | "warn" | "error"
|
||||
|
||||
type tipoOpSessao = {
|
||||
inquilino: string
|
||||
usuario: string
|
||||
parametros?: { [k: string]: string }
|
||||
}
|
||||
|
||||
type tipoLog = {
|
||||
detalhes?: unknown[]
|
||||
__filename?: string
|
||||
local?: string
|
||||
parametros?: { [k: string]: string }
|
||||
}
|
||||
|
||||
export type tipoLoggerLog = (
|
||||
level: tipoLevel,
|
||||
mensagem: string,
|
||||
op_tipoLog?: tipoLog,
|
||||
) => Promise<[objeto: tipoLokiObjeto, erro?: string]>
|
||||
|
||||
export type TipoLoggerSessao = (sess: tipoOpSessao) => tipoLoggerLog
|
||||
|
||||
export type tipoLogger = (amb: {
|
||||
app: string
|
||||
eProducao: boolean
|
||||
parametros?: {
|
||||
[k: string]: string
|
||||
}
|
||||
}) => TipoLoggerSessao
|
||||
|
||||
export const logger: tipoLogger =
|
||||
({ app: app_e, eProducao, parametros: parametrosAmbiente }) =>
|
||||
({ inquilino, usuario, parametros: parametrosSessao }) =>
|
||||
async (level, mensagem, op_tipoLog) => {
|
||||
let {
|
||||
__filename,
|
||||
detalhes,
|
||||
local,
|
||||
parametros: parametrosLog,
|
||||
} = op_tipoLog || {}
|
||||
|
||||
const app = `${eProducao ? "" : "DEV-"}${app_e}`
|
||||
|
||||
if (cwd && __filename) {
|
||||
__filename = __filename.replace(cwd, "")
|
||||
}
|
||||
|
||||
if (local) {
|
||||
detalhes = [`${nomeVariavel({ local })}="${local}"`, ...(detalhes || [])]
|
||||
}
|
||||
|
||||
if (__filename) {
|
||||
detalhes = [
|
||||
`${nomeVariavel({ __filename })}="${__filename}"`,
|
||||
...(detalhes || []),
|
||||
]
|
||||
}
|
||||
|
||||
const timestamp = `${Date.now()}000000`
|
||||
|
||||
const mainLog = detalhes?.length
|
||||
? `${mensagem} | ${detalhes.map((d) => JSON.stringify(d)).join(" | ")}`
|
||||
: mensagem
|
||||
|
||||
const payload: tipoLokiObjeto["streams"][number] = {
|
||||
stream: {
|
||||
app,
|
||||
inquilino,
|
||||
usuario,
|
||||
level,
|
||||
...(parametrosAmbiente || {}),
|
||||
...(parametrosSessao || {}),
|
||||
...(parametrosLog || {}),
|
||||
},
|
||||
values: [
|
||||
[
|
||||
timestamp,
|
||||
mainLog, // Linha de log direta
|
||||
],
|
||||
],
|
||||
}
|
||||
|
||||
const objeto: tipoLokiObjeto = { streams: [payload] }
|
||||
|
||||
const response = await postLogger({ objeto })
|
||||
|
||||
return response
|
||||
}
|
||||
0
src/postgres.ts
Normal file → Executable file
0
src/postgres.ts
Normal file → Executable file
63
src/situacoes.ts
Normal file
63
src/situacoes.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
export enum tiposSituacoesElicencie {
|
||||
modelo = "000_modelo",
|
||||
|
||||
vencida = "100_vencida",
|
||||
expirado = "200_expirado",
|
||||
alerta = "300_alerta",
|
||||
|
||||
protocoladafora = "350_protocoladafora",
|
||||
protocolada = "400_protocolada",
|
||||
protocoladaApenas = "430_protocolada",
|
||||
protocolada_alteracao = "450_protocolada",
|
||||
|
||||
prazo = "500_prazo",
|
||||
emitida = "515_emitida",
|
||||
valida = "518_valida",
|
||||
novo = "520_novo",
|
||||
recebido = "521_recebido",
|
||||
em_andamento = "530_em_andamento",
|
||||
|
||||
aguardando = "530_aguardando",
|
||||
aguardandoresposta = "540_aguardandoresposta",
|
||||
suspensaotemporaria = "540_suspensaotemporaria",
|
||||
cancelada = "550_cancelada",
|
||||
execucao = "560_execucao",
|
||||
pendente = "570_pendente",
|
||||
executadafora = "600_executadafora",
|
||||
executada = "700_executada",
|
||||
naoexecutada = "701_naoexecutada",
|
||||
concluida = "730_concluida",
|
||||
respondido_negado = "740_respondido_negado",
|
||||
respondido_aceito = "741_respondido_aceito",
|
||||
|
||||
atendidoparcial = "742_atendidoparcial",
|
||||
naoatendido = "743_naoatendido",
|
||||
atendido = "744_atendido",
|
||||
|
||||
renovada = "760_renovada",
|
||||
finalizada = "800_finalizada",
|
||||
emitirnota = "101_emitirnota",
|
||||
faturaatrasada = "301_faturaatrasada",
|
||||
pagarfatura = "302_pagarfatura",
|
||||
aguardandoconfirmacao = "531_aguardandoconfirmacao",
|
||||
agendado = "701_agendado",
|
||||
faturapaga = "801_faturapaga",
|
||||
excluida = "999_excluida",
|
||||
|
||||
// situacoes outorgas
|
||||
// Requerido
|
||||
// Vigente
|
||||
// Em renovação
|
||||
// Arquivado
|
||||
|
||||
requerida = "401_requerida",
|
||||
vigente = "516_vigente",
|
||||
emrenovacao = "402_emrenovacao",
|
||||
arquivada = "801_arquivada",
|
||||
aguardando_sincronizacao = "999_aguardando_sincronizacao",
|
||||
|
||||
nao_conforme = "710_nao_conforme",
|
||||
conforme = "720_conforme",
|
||||
nao_aplicavel = "730_nao_aplicavel",
|
||||
parcial = "715_parcial",
|
||||
}
|
||||
0
src/teste.ts
Normal file → Executable file
0
src/teste.ts
Normal file → Executable file
0
src/testes-de-variaveis/index.ts
Normal file → Executable file
0
src/testes-de-variaveis/index.ts
Normal file → Executable file
0
src/testes-de-variaveis/umaFuncao.ts
Normal file → Executable file
0
src/testes-de-variaveis/umaFuncao.ts
Normal file → Executable file
0
src/testes-de-variaveis/umaVariavel.ts
Normal file → Executable file
0
src/testes-de-variaveis/umaVariavel.ts
Normal file → Executable file
0
src/testes/TipagemRotas.test.ts
Normal file → Executable file
0
src/testes/TipagemRotas.test.ts
Normal file → Executable file
0
src/texto_busca.ts
Normal file → Executable file
0
src/texto_busca.ts
Normal file → Executable file
18
src/tipagemRotas.ts
Normal file → Executable file
18
src/tipagemRotas.ts
Normal file → Executable file
|
|
@ -63,9 +63,10 @@ export class TipagemRotas<T extends { [q: string]: any }> {
|
|||
*/
|
||||
|
||||
endereco(query: T, usarComoHash?: boolean) {
|
||||
const url = new URL(
|
||||
typeof window !== "undefined" ? window.location.href : "http://localhost",
|
||||
)
|
||||
const win =
|
||||
(typeof globalThis !== "undefined" && (globalThis as any).window) ||
|
||||
undefined
|
||||
const url = new URL(win ? win.location.href : "http://localhost")
|
||||
|
||||
url.pathname = this.caminho
|
||||
|
||||
|
|
@ -95,8 +96,11 @@ export class TipagemRotas<T extends { [q: string]: any }> {
|
|||
if (this._acaoIr) {
|
||||
this._acaoIr(this.endereco({ ...query }))
|
||||
} else {
|
||||
if (typeof window != "undefined") {
|
||||
window.location.href = this.endereco({ ...query })
|
||||
const win =
|
||||
(typeof globalThis !== "undefined" && (globalThis as any).window) ||
|
||||
undefined
|
||||
if (win) {
|
||||
win.location.href = this.endereco({ ...query })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -110,8 +114,8 @@ export class TipagemRotas<T extends { [q: string]: any }> {
|
|||
const url = urlEntrada
|
||||
? new URL(urlEntrada)
|
||||
: new URL(
|
||||
typeof window !== "undefined"
|
||||
? window.location.href
|
||||
typeof globalThis !== "undefined" && (globalThis as any).window
|
||||
? (globalThis as any).window.location.href
|
||||
: "http://localhost",
|
||||
)
|
||||
const query = url.searchParams
|
||||
|
|
|
|||
235
src/tipoFiltro.26.ts
Normal file
235
src/tipoFiltro.26.ts
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
import { z } from "zod"
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* 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
|
||||
============================================================================= */
|
||||
|
||||
export enum operadores26 {
|
||||
"=" = "=",
|
||||
"!=" = "!=",
|
||||
">" = ">",
|
||||
">=" = ">=",
|
||||
"<" = "<",
|
||||
"<=" = "<=",
|
||||
like = "like",
|
||||
in = "in",
|
||||
}
|
||||
|
||||
export enum agrupadores26 {
|
||||
E = "E",
|
||||
OU = "OU",
|
||||
}
|
||||
|
||||
type PgOpsNumber = {
|
||||
[K in Extract<operadores26, "=" | "!=" | ">" | ">=" | "<" | "<=">]?: number
|
||||
} & {
|
||||
[K in Extract<operadores26, "in">]?: number[]
|
||||
}
|
||||
|
||||
type PgOpsString = {
|
||||
[K in Extract<operadores26, "=" | "!=" | "like">]?: string
|
||||
} & {
|
||||
[K in Extract<operadores26, "in">]?: string[]
|
||||
}
|
||||
|
||||
type PgOpsBoolean = {
|
||||
[K in Extract<operadores26, "=" | "!=">]?: boolean
|
||||
} & {
|
||||
[K in Extract<operadores26, "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>[]
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
VALIDAÇÃO ESTRUTURAL (ZOD)
|
||||
============================================================================= */
|
||||
|
||||
const zOperadores = z.nativeEnum(operadores26)
|
||||
const zValor = z.any()
|
||||
const zCondicao = z.record(zOperadores, zValor)
|
||||
|
||||
export const zFiltro26: z.ZodType<any> = z.lazy(() =>
|
||||
z
|
||||
.object({
|
||||
E: z.array(zFiltro26).optional(),
|
||||
OU: z.array(zFiltro26).optional(),
|
||||
})
|
||||
.catchall(z.union([zCondicao, zFiltro26])),
|
||||
)
|
||||
|
||||
/* =============================================================================
|
||||
EXEMPLO DE USO
|
||||
============================================================================= */
|
||||
|
||||
type Pessoa = {
|
||||
codigo: string
|
||||
nome: string
|
||||
idade: number
|
||||
carro: {
|
||||
modelo: string
|
||||
ano: number
|
||||
}
|
||||
}
|
||||
|
||||
export const criarFiltro26 = <T>(filtro: tipoFiltro26<T>) => filtro
|
||||
|
||||
const _filtro = criarFiltro26<Pessoa>({
|
||||
idade: { [operadores26[">="]]: 18 },
|
||||
|
||||
[agrupadores26.OU]: [
|
||||
{ nome: { [operadores26.like]: "%pa%" } },
|
||||
{
|
||||
[agrupadores26.E]: [
|
||||
{ carro: { ano: { [operadores26["="]]: 2020 } } },
|
||||
{ carro: { modelo: { [operadores26.in]: ["Civic", "Corolla"] } } },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
0
src/unidades_medida.ts
Normal file → Executable file
0
src/unidades_medida.ts
Normal file → Executable file
0
src/uuid.ts
Normal file → Executable file
0
src/uuid.ts
Normal file → Executable file
0
src/variaveisComuns.ts
Normal file → Executable file
0
src/variaveisComuns.ts
Normal file → Executable file
Loading…
Add table
Add a link
Reference in a new issue