Compare commits

..

No commits in common. "master" and "master-dayjs" have entirely different histories.

44 changed files with 1692 additions and 3354 deletions

23
.vscode/settings.json vendored
View file

@ -4,10 +4,8 @@
"source.fixAll.biome": "always" "source.fixAll.biome": "always"
}, },
"editor.defaultFormatter": "biomejs.biome", "editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "biomejs.biome" "editor.defaultFormatter": "vscode.typescript-language-features"
}, },
"[javascriptreact]": { "[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome" "editor.defaultFormatter": "biomejs.biome"
@ -25,21 +23,6 @@
"editor.defaultFormatter": "biomejs.biome" "editor.defaultFormatter": "biomejs.biome"
}, },
"[vue]": { "[vue]": {
"editor.defaultFormatter": "biomejs.biome" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, }
"[css]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[html]": {
"editor.defaultFormatter": "biomejs.biome"
},
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.suggest.autoImports": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.rulers": [100],
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
} }

234
AGENTS.md
View file

@ -1,234 +0,0 @@
# AGENTS.md — Guia para Assistentes de IA
> **Este arquivo descreve os padrões, convenções e arquitetura do projeto `p-comuns`.**
> Leia este arquivo antes de sugerir ou gerar qualquer código.
---
## 🏗️ Visão Geral do Projeto
`p-comuns` é um **pacote compartilhado** (npm monorepo-like) usado como dependência em todos os subprojetos da plataforma **e-licencie**. Ele provê:
- Tipos TypeScript compartilhados (rotas, filtros, situações, UUIDs...)
- Utilitários de back-end (postgres, cache em memória, dayjs...)
- Utilitários de front-end (Vue 3 + TSX)
- Constantes e enums globais
---
## ⚙️ Stack Tecnológica
| Camada | Tecnologia | Versão |
|--------|-----------|--------|
| Linguagem | TypeScript | ~5.9.x |
| Runtime (back) | Node.js | ≥20 |
| Framework (front) | Vue 3 | Composition API + `<script setup>` |
| JSX/TSX | Vue TSX / React-like TSX | via `jsxRuntime` |
| Linter/Formatter | Biome | 2.4.x |
| Bundler | tsup | 8.x |
| Package manager | pnpm | com workspaces |
| Validação | Zod | 4.x |
| Utilitários de data | dayjs | 1.11.x |
---
## 📁 Estrutura do `src/`
```
src/
├── index.ts # Entry point — exporta tudo que é público
├── constantes.ts # Constantes globais (enums, valores fixos)
├── situacoes.ts # Status/situações dos processos
├── tipagemRotas.ts # Tipagem forte de rotas da API
├── filtroDelta.ts # Sistema de filtros tipados (operadores PG)
├── uuid.ts # Geração e validação de UUIDs
├── dayjs26.ts # Wrapper do dayjs com locale e plugins
├── extensoes.ts # Extensões de tipos nativos
├── texto_busca.ts # Utilitários de busca em texto
├── variaveisComuns.ts # Variáveis de ambiente compartilhadas
├── postgres.ts # Cliente PostgreSQL base
├── cacheMemoria.ts # Cache em memória (Map com TTL)
├── aleatorio.ts # Utilitários de aleatoriedade
├── consulta.ts # Helpers de consulta SQL
├── instalarAmbiente.ts # Setup de ambiente (dev/prod)
├── graficosPilao.ts # Tipos para gráficos do PILÃO
├── ecosistema/ # Tipos do ecossistema de módulos
└── testes/ # Testes unitários (Vitest)
```
---
## 📐 Convenções de Código
### TypeScript
- **Strict mode** SEMPRE ligado (`"strict": true`)
- **Sem `any` explícito** — use tipos genéricos ou `unknown`
- **Sem `!` (non-null assertion)** — trate o `null`/`undefined` explicitamente
- **Arrays**: usar `T[]` em vez de `Array<T>` (shorthand)
- **Imports** ordenados automaticamente pelo Biome
- **Enums** sempre com inicializadores explícitos
- **Parâmetros** não podem ser reatribuídos
### Nomenclatura
```typescript
// Tipos e interfaces: PascalCase
type TipoUsuario = { ... }
interface IRepositorio { ... }
// Constantes: camelCase (sem SCREAMING_SNAKE_CASE, exceto enums legados)
const configuracaoBase = { ... }
// Funções: camelCase, verbos
const calcularTotal = (itens: Item[]) => { ... }
const buscarUsuarioPorId = async (id: UUID) => { ... }
// Arquivos: camelCase para utilitários, PascalCase para componentes Vue
// ✅ tipoFiltro.ts, variaveisComuns.ts
// ✅ MeuComponente.vue, BotaoAcao.vue
```
### Vue 3 (Composition API)
```vue
<script setup lang="ts">
// Sempre usar <script setup lang="ts">
// Macros globais disponíveis (sem import): defineProps, defineEmits,
// defineExpose, withDefaults, defineModel, defineOptions, defineSlots
const props = defineProps<{
titulo: string
itens: Item[]
}>()
const emit = defineEmits<{
selecionar: [item: Item]
fechar: []
}>()
</script>
```
- **Sem Vue Options API** — sempre Composition API
- **Props não devem ser desestruturadas** (quebra reatividade Vue 3)
- **`v-for` sempre com `:key`** — use o ID do item, nunca o índice!
- **`v-if` e `v-for` nunca no mesmo elemento** — use `<template v-for>`
- **Atributos em multiline** quando há mais de 2 props
### TSX (componentes em `.tsx`)
```tsx
// Componente funcional Vue em TSX
import { defineComponent, ref } from "vue"
export const MeuComponente = defineComponent({
props: {
titulo: { type: String, required: true },
},
setup(props) {
const contador = ref(0)
return () => (
<div class="meu-componente">
<h1>{props.titulo}</h1>
<button onClick={() => contador.value++}>{contador.value}</button>
</div>
)
},
})
```
---
## 🔧 Biome — Regras de Lint Importantes
### Erros (bloqueiam o build)
| Regra | Descrição |
|-------|-----------|
| `noUnusedVariables` | Variáveis definidas e não usadas |
| `noUnusedImports` | Imports não utilizados |
| `noVoidTypeReturn` | Função `void` retornando valor |
| `noVueDataObjectDeclaration` | Vue 2 `data: {}` — usar função |
| `noVueDuplicateKeys` | Chaves duplicadas em objetos Vue |
| `noVueSetupPropsReactivityLoss` | Desestruturar `props` em `setup()` |
| `noVueVIfWithVFor` | `v-if` + `v-for` no mesmo elemento |
| `useVueVForKey` | `v-for` sem `:key` |
| `useVueValidTemplateRoot` | Template sem raiz única (Vue 2) |
### Warnings (code smells — corrija quando possível)
| Regra | Descrição |
|-------|-----------|
| `useArrowFunction` | **Sempre use arrow function** — `function` é erro |
| `noNonNullAssertion` | Evite `!` — trate o null |
| `noDelete` | `delete obj.prop` é lento |
| `noEmptyBlockStatements` | Blocos `{}` vazios |
| `noArrayIndexKey` | `:key` com índice do array |
| `noDangerouslySetInnerHtml` | `innerHTML` perigoso |
| `noExcessiveCognitiveComplexity` | Função muito complexa (max: 20) |
---
## 📦 Como Outros Projetos Consomem Este Pacote
```json
// biome.json do subprojeto (ex: PILAO-FRONT)
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["./node_modules/p-comuns/Documentos/biome.json"],
"files": {
"includes": ["src/**/*.{js,ts,jsx,tsx,vue}"]
}
}
```
```json
// .vscode/settings.json do subprojeto
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "always",
"source.fixAll.biome": "always"
},
"[vue]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"editor.rulers": [100],
"files.eol": "\n"
}
```
---
## 🚀 Scripts
```bash
pnpm biome # Formata + lint com auto-fix
pnpm check # biome + tsc --noEmit (sem emitir arquivos)
pnpm build # Bump de versão + biome + tsup + pack
pnpm teste # Vitest (testes unitários)
```
---
## ⚠️ O que NÃO fazer
- ❌ Não use `eslint` — o projeto usa Biome
- ❌ Não use `prettier` — o projeto usa Biome
- ❌ Não use `function` nomeada — sempre arrow function (`const fn = () => {}`)
- ❌ Não use Vue Options API — sempre Composition API
- ❌ Não desestrure `props` diretamente (quebra reatividade)
- ❌ Não use `any` — use `unknown` + type narrowing
- ❌ Não use índice como `:key` no `v-for`
- ❌ Não quebre linhas com mais de 100 caracteres
- ❌ Não use ponto-e-vírgula no final (Biome removerá)
---
## 📚 Referências
- [Biome 2.x Docs](https://biomejs.dev)
- [Vue 3 Composition API](https://vuejs.org/guide/composition-api)
- [Zod v4](https://zod.dev)
- [tsup](https://tsup.egoist.dev)

View file

@ -6,20 +6,12 @@
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": true, "recommended": true,
"correctness": { "correctness": {
"noUnusedVariables": "error", "noUnusedVariables": "error",
"noUnusedImports": "error", "noUnusedImports": "error",
"noEmptyPattern": "off", "noEmptyPattern": "off",
"useExhaustiveDependencies": "off", "useExhaustiveDependencies": "off"
"noVoidTypeReturn": "error",
"noVueDataObjectDeclaration": "error",
"noVueDuplicateKeys": "error",
"noVueReservedKeys": "error",
"noVueReservedProps": "error",
"noVueSetupPropsReactivityLoss": "warn"
}, },
"style": { "style": {
"noParameterAssign": "error", "noParameterAssign": "error",
"useAsConstAssertion": "error", "useAsConstAssertion": "error",
@ -29,125 +21,44 @@
"useSingleVarDeclarator": "error", "useSingleVarDeclarator": "error",
"noUnusedTemplateLiteral": "error", "noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error", "useNumberNamespace": "error",
"noInferrableTypes": "error", "noInferrableTypes": "error"
"useArrayLiterals": "error",
"useConsistentArrayType": {
"level": "error",
"options": { "syntax": "shorthand" }
}, },
"useShorthandAssign": "error",
"noNonNullAssertion": "warn"
},
"suspicious": { "suspicious": {
"noDebugger": "off", "noDebugger": "off",
"noDoubleEquals": "off", "noDoubleEquals": "off",
"noExplicitAny": "off", "noExplicitAny": "off",
"noApproximativeNumericConstant": "off", "noApproximativeNumericConstant": "off",
"noAsyncPromiseExecutor": "off", "noAsyncPromiseExecutor": "off"
"noEmptyBlockStatements": "off",
"noConsole": "off",
"noArrayIndexKey": "warn"
}, },
"complexity": { "complexity": {
"noUselessConstructor": "off", "noUselessConstructor": "off",
"noBannedTypes": "off", "noBannedTypes": "off",
"useLiteralKeys": "off", "useLiteralKeys": "off",
"useArrowFunction": "error", "useArrowFunction": "warn",
"useDateNow": "off", "useDateNow": "off",
"noUselessFragments": "off", "noUselessFragments": "off"
"noExcessiveCognitiveComplexity": "off",
"noImportantStyles": "off"
}, },
"performance": { "performance": {
"noAccumulatingSpread": "off", "noAccumulatingSpread": "off"
"noDelete": "off"
}, },
"a11y": { "a11y": {
"useSemanticElements": "off", "useSemanticElements": "off"
"useAltText": "warn",
"useButtonType": "warn"
},
"security": {
"noDangerouslySetInnerHtml": "warn"
},
"nursery": {
"noVueArrowFuncInWatch": "warn",
"noVueVIfWithVFor": "error",
"useVueConsistentDefinePropsDeclaration": "warn",
"useVueConsistentVBindStyle": "warn",
"useVueConsistentVOnStyle": "warn",
"useVueDefineMacrosOrder": "warn",
"useVueVForKey": "error",
"useVueValidTemplateRoot": "error",
"useVueValidVBind": "error",
"useVueValidVIf": "error",
"useVueValidVElse": "error",
"useVueValidVElseIf": "error",
"useVueValidVOn": "warn",
"useVueValidVHtml": "warn"
} }
} }
}, },
"formatter": { "formatter": {
"enabled": true, "enabled": true,
"indentStyle": "space", "indentStyle": "space",
"indentWidth": 2, "indentWidth": 2
"lineWidth": 100,
"lineEnding": "lf"
}, },
"javascript": { "javascript": {
"globals": [
"defineProps",
"defineEmits",
"defineExpose",
"withDefaults",
"defineModel",
"defineOptions",
"defineSlots"
],
"parser": {
"unsafeParameterDecoratorsEnabled": true
},
"formatter": { "formatter": {
"enabled": true, "enabled": true,
"semicolons": "asNeeded", "semicolons": "asNeeded",
"arrowParentheses": "always", "arrowParentheses": "always",
"bracketSameLine": false, "bracketSameLine": false,
"trailingCommas": "all", "trailingCommas": "all",
"attributePosition": "multiline", "attributePosition": "multiline"
"quoteStyle": "double",
"jsxQuoteStyle": "double",
"bracketSpacing": true
}
},
"css": {
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"quoteStyle": "double"
},
"linter": {
"enabled": true
}
},
"html": {
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
} }
} }
} }

151
README.md
View file

@ -1,143 +1,124 @@
# `p-comuns` — Pacote Compartilhado e-licencie ## ✅ Uso do BiomeJS para Autoformatação
Pacote de tipos, utilitários e configurações compartilhadas entre todos os subprojetos da plataforma **e-licencie** (back-end Node.js, front-end Vue 3 / TSX). Este guia mostra como configurar o [BiomeJS](https://biomejs.dev) para formatar e analisar código JavaScript/TypeScript no seu projeto.
--- ---
## ✅ Configuração do BiomeJS nos Subprojetos ### 1. Incluir o pacote de configuração comum
Este guia mostra como usar a configuração base do Biome disponível neste pacote (`Documentos/biome.json`). Todos os subprojetos herdam essas regras via `extends`. Certifique-se de que o pacote `p-comuns` (ou outro com a configuração compartilhada) esteja disponível no seu projeto. Ele deve conter o arquivo `Documentos/biome.json`.
### 1. Adicionar o `p-comuns` como dependência
```bash
pnpm add --save-dev p-comuns
# ou atualizar se já existir:
pnpm up p-comuns pnpm up p-comuns
```
--- ---
### 2. Instalar o Biome ### 2. Instalar o Biome com `pnpm`
```bash ```bash
pnpm add --save-dev --save-exact @biomejs/biome@2.4.0 pnpm add --save-dev --save-exact @biomejs/biome@2.1.4
``` ```
> 🎯 Use `--save-exact` para garantir consistência de versões entre ambientes. > 🎯 Use `--save-exact` para garantir consistência de versões entre ambientes.
--- ---
### 3. Criar `biome.json` na raiz do subprojeto ### 3. Criar o arquivo de configuração na raiz do projeto
Crie um arquivo chamado `biome.json` com o seguinte conteúdo:
```json ```json
{ {
"$schema": "node_modules/@biomejs/biome/configuration_schema.json", "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["node_modules/p-comuns/Documentos/biome.json"], "extends": ["./node_modules/p-comuns/Documentos/biome.json"],
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": { "files": {
"includes": ["**/*.{ts,tsx,vue}"] "includes": ["src/**/*.{js,ts,jsx,tsx}"]
} }
} }
``` ```
> `vcs.useIgnoreFile: true` faz o Biome respeitar o `.gitignore` automaticamente — arquivos como `dist/`, `node_modules/` etc. são ignorados sem configuração adicional. > ⚠️ Verifique o caminho correto do `extends` relativo à raiz do seu projeto. Use `./` sempre que possível para evitar erros de resolução.
--- ---
### 4. Adicionar scripts no `package.json` ### 4. Adicionar script no `package.json`
Inclua o comando abaixo em `"scripts"`:
```json ```json
{ {
"scripts": { "scripts": {
"biome": "pnpm exec biome check --write", "biome": "pnpm exec biome check --write",
"check": "pnpm run biome && npx tsc --noEmit"
} }
} }
``` ```
Isso permite executar:
```bash
pnpm biome
```
> O comando irá **formatar e aplicar as regras de lint** nos arquivos do diretório `src/`.
--- ---
### 5. Configurar o VS Code (`.vscode/settings.json`) ### ✅ Dica extra: formatar todos os arquivos
Se quiser aplicar o Biome a todo o projeto (não só `src/`), altere o include:
```json ```json
"includes": ["**/*.{js,ts,jsx,tsx}"]
```
adicionar em .vscode/settings.json
{ {
"editor.defaultFormatter": "biomejs.biome", "editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "always",
"source.fixAll.biome": "always"
},
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" }, "[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
"[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"[vue]": { "editor.defaultFormatter": "biomejs.biome" },
"[css]": { "editor.defaultFormatter": "biomejs.biome" },
"[json]": { "editor.defaultFormatter": "biomejs.biome" }, "[json]": { "editor.defaultFormatter": "biomejs.biome" },
"[jsonc]": { "editor.defaultFormatter": "biomejs.biome" }, "[jsonc]": { "editor.defaultFormatter": "biomejs.biome" },
"editor.rulers": [100], "[vue]": {"editor.defaultFormatter": "octref.vetur"},
"files.eol": "\n", "editor.codeActionsOnSave": {
"files.trimTrailingWhitespace": true, "source.organizeImports.biome": "always",
"files.insertFinalNewline": true "source.fixAll.biome": "always"
}
} }
```
> 💡 **Biome formata Vue `.vue` nativamente desde a v2.3** — não precisa do Prettier ou Vetur para formatação!
--- ---
## 🔑 Regras da configuração base (Documentos/biome.json) ## ✅ Sistema de Filtros (tipoFiltro26)
### O que está ativado: O sistema `tipoFiltro26` foi projetado para gerar automaticamente a tipagem de filtros compatíveis com operadores padrão do PostgreSQL, a partir de um tipo base `T`.
| Categoria | Regras notáveis |
|-----------|----------------|
| **Correctness** | `noUnusedVariables`, `noUnusedImports`, `noVueSetupPropsReactivityLoss` |
| **Vue 3 específico** | `noVueVIfWithVFor`, `useVueVForKey`, `noVueDuplicateKeys`, `noVueReservedKeys` |
| **Style** | `useAsConstAssertion`, `useSelfClosingElements`, `useConsistentArrayType` (shorthand `T[]`) |
| **Nursery Vue** | `noVueArrowFuncInWatch`, `useVueDefineMacrosOrder`, `useVueConsistentVBindStyle` |
| **Security** | `noDangerouslySetInnerHtml` (warn) |
### Globals do Vue (sem necessidade de importar):
`defineProps`, `defineEmits`, `defineExpose`, `withDefaults`, `defineModel`, `defineOptions`, `defineSlots`
### Formatação:
- Indentação: **2 espaços**
- Linha máxima: **100 caracteres**
- Aspas: **duplas**
- Ponto-e-vírgula: **apenas quando necessário**
- Trailing comma: **sempre**
- Line ending: **LF (`\n`)**
---
## ✅ Sistema de Filtros (filtroDelta)
O sistema `filtroDelta` foi projetado para gerar automaticamente a tipagem de filtros compatíveis com operadores padrão do PostgreSQL, a partir de um tipo base `T`.
**Principais características:** **Principais características:**
- Tipagem forte e segura (TypeScript) - Tipagem forte e segura (Typescript)
- Suporte a aninhamento de objetos - Suporte a aninhamento de objetos
- Operadores lógicos `E` (AND) e `OU` (OR) - Operadores lógicos `E` (AND) e `OU` (OR)
- Validação de operadores permitidos por tipo de dado (string, number, boolean) - Validação de operadores permitidos por tipo de dado (string, number, boolean)
### Estrutura do Filtro ### Estrutura do Filtro
O filtro segue uma estrutura onde chaves representam campos (simples ou aninhados) e valores representam condições com operadores específicos.
#### 1. Campos Simples #### 1. Campos Simples
```typescript ```typescript
{ idade: { ">=": 18 } } {
idade: { ">=": 18 }
}
``` ```
#### 2. Campos Aninhados #### 2. Campos Aninhados
```typescript ```typescript
{ carro: { ano: { "=": 2020 } } } {
carro: {
ano: { "=": 2020 }
}
}
``` ```
#### 3. Operadores Lógicos #### 3. Operadores Lógicos
@ -162,7 +143,7 @@ O sistema `filtroDelta` foi projetado para gerar automaticamente a tipagem de fi
} }
``` ```
#### 4. Exemplo Complexo Completo #### 4. Exemplo Complexo Complet
```typescript ```typescript
{ {
idade: { ">=": 18 }, idade: { ">=": 18 },
@ -178,25 +159,23 @@ O sistema `filtroDelta` foi projetado para gerar automaticamente a tipagem de fi
} }
``` ```
### Operadores Suportados (`operadoresDelta`) ### Operadores Suportados (`operadores26`)
- **Number**: `=`, `!=`, `>`, `>=`, `<`, `<=`, `in` Os operadores são fornecidos pelo enum `operadores26` e são restritos pelo tipo do campo:
- **String**: `=`, `!=`, `like`, `in`
- **Boolean**: `=`, `!=`, `in` * **Number**: `=`, `!=`, `>`, `>=`, `<`, `<=`, `in`
* **String**: `=`, `!=`, `like`, `in`
* **Boolean**: `=`, `!=`, `in`
> **Nota:** Atualmente não há suporte automático para `null`, `date`, `jsonb` ou `arrays` como tipos de campo raiz (exceto arrays dentro do operador `in`).
### Validação em Tempo de Execução (Zod) ### Validação em Tempo de Execução (Zod)
O sistema inclui um validador Zod `zFiltro26` para validação estrutural dos objetos de filtro recebidos (ex: via API).
```typescript ```typescript
import { zFiltroDelta } from "p-comuns" import { zFiltro26 } from './tipoFiltro.26';
// Valida a estrutura (não checa existência de colunas no DB) // Valida a estrutura (não checa existência de colunas no DB)
zFiltroDelta.parse(objetoFiltro) zFiltro26.parse(objetoFiltro);
``` ```
---
## 📚 Veja também
- [`AGENTS.md`](./AGENTS.md) — Guia para assistentes de IA (padrões, convenções, arquitetura)
- [Biome 2.x Docs](https://biomejs.dev)
- [Vue 3 Composition API](https://vuejs.org/guide/composition-api)

View file

@ -2,6 +2,6 @@
"$schema": "node_modules/@biomejs/biome/configuration_schema.json", "$schema": "node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["Documentos/biome.json"], "extends": ["Documentos/biome.json"],
"files": { "files": {
"includes": ["src/**/*.{js,ts,jsx,tsx,vue}"] "includes": ["src/**/*.{js,ts,jsx,tsx}"]
} }
} }

View file

@ -1,16 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var auditoria_exports = {};
module.exports = __toCommonJS(auditoria_exports);

View file

@ -44,7 +44,6 @@ var operadores = /* @__PURE__ */ ((operadores2) => {
operadores2["like"] = "like"; operadores2["like"] = "like";
operadores2["in"] = "in"; operadores2["in"] = "in";
operadores2["isNull"] = "isNull"; operadores2["isNull"] = "isNull";
operadores2["notIn"] = "notIn";
return operadores2; return operadores2;
})(operadores || {}); })(operadores || {});
const zOperadores = import_zod.default.enum([ const zOperadores = import_zod.default.enum([
@ -56,8 +55,7 @@ const zOperadores = import_zod.default.enum([
"<=", "<=",
"like", "like",
"in", "in",
"isNull", "isNull"
"notIn"
]); ]);
const zFiltro = import_zod.default.object({ const zFiltro = import_zod.default.object({
coluna: import_zod.default.string(), coluna: import_zod.default.string(),

View file

@ -1,52 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var dayjs26_exports = {};
__export(dayjs26_exports, {
defineDayjsBr: () => defineDayjsBr,
iniciarDayjsBr: () => iniciarDayjsBr
});
module.exports = __toCommonJS(dayjs26_exports);
const iniciarDayjsBr = ({
dayjs,
duration,
isSameOrAfter,
isSameOrBefore,
minMax,
relativeTime,
timezone,
utc,
weekOfYear
}) => {
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(weekOfYear);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
dayjs.extend(minMax);
dayjs.extend(relativeTime);
dayjs.extend(duration);
dayjs.locale("pt-br");
return dayjs;
};
const defineDayjsBr = iniciarDayjsBr;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defineDayjsBr,
iniciarDayjsBr
});

View file

@ -1,85 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var eLog_exports = {};
__export(eLog_exports, {
NivelLog: () => NivelLog,
NivelLogDetalhes: () => NivelLogDetalhes,
iniciarELog: () => iniciarELog
});
module.exports = __toCommonJS(eLog_exports);
var NivelLog = /* @__PURE__ */ ((NivelLog2) => {
NivelLog2["RASTREAMENTO"] = "RASTREAMENTO";
NivelLog2["DEPURACAO"] = "DEPURACAO";
NivelLog2["INFORMACAO"] = "INFORMACAO";
NivelLog2["AVISO"] = "AVISO";
NivelLog2["ERRO"] = "ERRO";
NivelLog2["CRITICO"] = "CRITICO";
return NivelLog2;
})(NivelLog || {});
const NivelLogDetalhes = {
["RASTREAMENTO" /* RASTREAMENTO */]: { peso: 1, rotulo: "Rastreamento", emoji: "\u{1F50D}", metodo: "debug" },
["DEPURACAO" /* DEPURACAO */]: { peso: 2, rotulo: "Depura\xE7\xE3o", emoji: "\u{1F41B}", metodo: "debug" },
["INFORMACAO" /* INFORMACAO */]: { peso: 3, rotulo: "Informa\xE7\xE3o", emoji: "\u2139\uFE0F", metodo: "info" },
["AVISO" /* AVISO */]: { peso: 4, rotulo: "Aviso", emoji: "\u26A0\uFE0F", metodo: "warn" },
["ERRO" /* ERRO */]: { peso: 5, rotulo: "Erro", emoji: "\u274C", metodo: "error" },
["CRITICO" /* CRITICO */]: { peso: 6, rotulo: "Cr\xEDtico", emoji: "\u{1F525}", metodo: "error" }
};
const iniciarELog = (opcoes) => {
const nivel = opcoes.nivelMinimo ?? "INFORMACAO" /* INFORMACAO */;
const pesoMinimo = NivelLogDetalhes[nivel].peso;
const emitir = (nivelLog, pr) => {
const config = NivelLogDetalhes[nivelLog];
if (config.peso < pesoMinimo) return;
const entrada = {
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
nivel: nivelLog,
app: opcoes.app,
origem: pr.origem,
mensagem: pr.mensagem,
...pr.dados !== void 0 ? { dados: pr.dados } : {}
};
console[config.metodo](
`${config.emoji} [${config.rotulo}] [${opcoes.app}] [${pr.origem}] ${pr.mensagem}`,
pr.dados !== void 0 ? pr.dados : ""
);
if (opcoes.arquivamento) {
opcoes.arquivamento(entrada, { app: opcoes.app, nivelMinimo: nivel });
}
};
return {
rastreamento: (pr) => emitir("RASTREAMENTO" /* RASTREAMENTO */, pr),
depuracao: (pr) => emitir("DEPURACAO" /* DEPURACAO */, pr),
info: (pr) => emitir("INFORMACAO" /* INFORMACAO */, pr),
aviso: (pr) => emitir("AVISO" /* AVISO */, pr),
erro: (pr) => emitir("ERRO" /* ERRO */, pr),
critico: (pr) => emitir("CRITICO" /* CRITICO */, pr)
};
};
const _log = iniciarELog({
app: "testando",
nivelMinimo: "INFORMACAO" /* INFORMACAO */,
arquivamento: () => {
}
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
NivelLog,
NivelLogDetalhes,
iniciarELog
});

View file

@ -1,159 +0,0 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var filtroDelta_exports = {};
__export(filtroDelta_exports, {
criarFiltroDelta: () => criarFiltroDelta,
iniciarFiltroDelta: () => iniciarFiltroDelta,
operadorFiltroDeltaDetalhes: () => operadorFiltroDeltaDetalhes,
zColunaFiltroDelta: () => zColunaFiltroDelta,
zCondicaoFiltroDelta: () => zCondicaoFiltroDelta,
zFiltroDelta: () => zFiltroDelta,
zOperadorFiltroDelta: () => zOperadorFiltroDelta
});
module.exports = __toCommonJS(filtroDelta_exports);
var import_zod = __toESM(require("zod"));
const zOperadorFiltroDelta = import_zod.default.enum([">", "<", ">=", "<=", "=", "!=", "in", "like", "\u2229"]);
const operadorFiltroDeltaDetalhes = {
">": {
rotulo: "Maior que",
descricao: "O valor de A deve ser maior que o valor de B"
},
"<": {
rotulo: "Menor que",
descricao: "O valor de A deve ser menor que o valor de B"
},
">=": {
rotulo: "Maior ou igual a",
descricao: "O valor de A deve ser maior ou igual ao valor de B"
},
"<=": {
rotulo: "Menor ou igual a",
descricao: "O valor de A deve ser menor ou igual ao valor de B"
},
"=": {
rotulo: "Igual a",
descricao: "O valor de A deve ser igual ao valor de B"
},
"!=": {
rotulo: "Diferente de",
descricao: "O valor de A deve ser diferente do valor de B"
},
in: {
rotulo: "Est\xE1 em",
descricao: "O valor de A deve estar presente na cole\xE7\xE3o ou lista definida em B"
},
like: {
rotulo: "Cont\xE9m",
descricao: "O valor de A deve conter o texto informado em B"
},
"\u2229": {
rotulo: "Interse\xE7\xE3o",
descricao: "A e B devem possuir pelo menos um elemento em comum"
}
};
const regexIdCondicaoFiltroDelta = /^\{[\w:]+\}$/;
const regexColunaFiltroDelta = /^\w+(\.\w+)*$/;
const zColunaFiltroDelta = import_zod.default.string().regex(regexColunaFiltroDelta, "Coluna inv\xE1lida").describe("nome da coluna ou caminho aninhado do jsonb");
const zCondicaoFiltroDelta = import_zod.default.object({
/**
* Identificador único da condição.
*
* Exemplo:
* {1}
*/
id: import_zod.default.string().describe("id da condi\xE7\xE3o do filtro").regex(regexIdCondicaoFiltroDelta, "O id deve seguir o formato {identificador}"),
/**
* Nome da coluna ou caminho jsonb.
*/
coluna: zColunaFiltroDelta,
/**
* Operador da comparação.
*/
operador: zOperadorFiltroDelta,
/**
* Valor utilizado na comparação.
*/
valor: import_zod.default.any().describe("valor de compara\xE7\xE3o")
});
const formulaFiltroDeltaValida = (formula) => {
const tokensPermitidos = formula.match(/\{[\w:]+\}|\bNAO\b|\bE\b|\bOU\b|\(|\)/g) || [];
const formulaReconstruida = tokensPermitidos.join("");
const formulaOriginalSemEspacos = formula.replace(/\s+/g, "");
const formulaReconstruidaSemEspacos = formulaReconstruida.replace(/\s+/g, "");
if (formulaOriginalSemEspacos !== formulaReconstruidaSemEspacos) {
return false;
}
const expressaoLogica = formula.replace(/\{[\w:]+\}/g, "true").replace(/\bNAO\b/g, "!").replace(/\bE\b/g, "&&").replace(/\bOU\b/g, "||");
try {
new Function(`return (${expressaoLogica})`)();
return true;
} catch {
return false;
}
};
const zFiltroDelta = import_zod.default.object({
/**
* Lista de condições disponíveis.
*/
condicoes: import_zod.default.array(zCondicaoFiltroDelta),
/**
* Fórmula lógica que combina as condições.
*/
formula: import_zod.default.string().refine(formulaFiltroDeltaValida, {
message: "F\xF3rmula inv\xE1lida. Use apenas refer\xEAncias de condi\xE7\xF5es {id} ou {id:sufixo}, operadores E/OU/NAO e par\xEAnteses."
})
}).superRefine((value, ctx) => {
const idsCondicoes = new Set(value.condicoes.map((condicao) => condicao.id));
const referenciasFormula = value.formula.match(/\{[\w:]+\}/g) || [];
for (const referencia of referenciasFormula) {
if (!idsCondicoes.has(referencia)) {
ctx.addIssue({
code: "custom",
path: ["formula"],
message: `A refer\xEAncia ${referencia} n\xE3o existe em condicoes.`
});
}
}
});
const criarFiltroDelta = (filtro) => zFiltroDelta.parse(filtro);
const iniciarFiltroDelta = () => {
return {
criarFiltroDelta
};
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
criarFiltroDelta,
iniciarFiltroDelta,
operadorFiltroDeltaDetalhes,
zColunaFiltroDelta,
zCondicaoFiltroDelta,
zFiltroDelta,
zOperadorFiltroDelta
});

View file

@ -16,16 +16,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
var index_exports = {}; var index_exports = {};
module.exports = __toCommonJS(index_exports); module.exports = __toCommonJS(index_exports);
__reExport(index_exports, require("./aleatorio"), module.exports); __reExport(index_exports, require("./aleatorio"), module.exports);
__reExport(index_exports, require("./auditoria"), module.exports);
__reExport(index_exports, require("./cacheMemoria"), module.exports); __reExport(index_exports, require("./cacheMemoria"), module.exports);
__reExport(index_exports, require("./constantes"), module.exports); __reExport(index_exports, require("./constantes"), module.exports);
__reExport(index_exports, require("./consulta"), module.exports); __reExport(index_exports, require("./consulta"), module.exports);
__reExport(index_exports, require("./dayjs26"), module.exports); __reExport(index_exports, require("./dayjs"), module.exports);
__reExport(index_exports, require("./ecosistema"), module.exports); __reExport(index_exports, require("./ecosistema"), module.exports);
__reExport(index_exports, require("./eLog"), module.exports);
__reExport(index_exports, require("./extensoes"), module.exports); __reExport(index_exports, require("./extensoes"), module.exports);
__reExport(index_exports, require("./extensoes"), module.exports); __reExport(index_exports, require("./extensoes"), module.exports);
__reExport(index_exports, require("./filtroDelta"), module.exports);
__reExport(index_exports, require("./local"), module.exports); __reExport(index_exports, require("./local"), module.exports);
__reExport(index_exports, require("./postgres"), module.exports); __reExport(index_exports, require("./postgres"), module.exports);
__reExport(index_exports, require("./produtos"), module.exports); __reExport(index_exports, require("./produtos"), module.exports);
@ -34,25 +31,20 @@ __reExport(index_exports, require("./testes-de-variaveis"), module.exports);
__reExport(index_exports, require("./texto_busca"), module.exports); __reExport(index_exports, require("./texto_busca"), module.exports);
__reExport(index_exports, require("./tipagemRotas"), module.exports); __reExport(index_exports, require("./tipagemRotas"), module.exports);
__reExport(index_exports, require("./tipagemRotas"), module.exports); __reExport(index_exports, require("./tipagemRotas"), module.exports);
__reExport(index_exports, require("./tipoFiltro.26"), module.exports);
__reExport(index_exports, require("./unidades_medida"), module.exports); __reExport(index_exports, require("./unidades_medida"), module.exports);
__reExport(index_exports, require("./uuid"), module.exports); __reExport(index_exports, require("./uuid"), module.exports);
__reExport(index_exports, require("./variaveisComuns"), module.exports); __reExport(index_exports, require("./variaveisComuns"), module.exports);
__reExport(index_exports, require("./zCoordenadas"), module.exports);
__reExport(index_exports, require("./zDocumento"), module.exports);
__reExport(index_exports, require("./zodCustomizados"), module.exports);
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = { 0 && (module.exports = {
...require("./aleatorio"), ...require("./aleatorio"),
...require("./auditoria"),
...require("./cacheMemoria"), ...require("./cacheMemoria"),
...require("./constantes"), ...require("./constantes"),
...require("./consulta"), ...require("./consulta"),
...require("./dayjs26"), ...require("./dayjs"),
...require("./ecosistema"), ...require("./ecosistema"),
...require("./eLog"),
...require("./extensoes"), ...require("./extensoes"),
...require("./extensoes"), ...require("./extensoes"),
...require("./filtroDelta"),
...require("./local"), ...require("./local"),
...require("./postgres"), ...require("./postgres"),
...require("./produtos"), ...require("./produtos"),
@ -61,10 +53,8 @@ __reExport(index_exports, require("./zodCustomizados"), module.exports);
...require("./texto_busca"), ...require("./texto_busca"),
...require("./tipagemRotas"), ...require("./tipagemRotas"),
...require("./tipagemRotas"), ...require("./tipagemRotas"),
...require("./tipoFiltro.26"),
...require("./unidades_medida"), ...require("./unidades_medida"),
...require("./uuid"), ...require("./uuid"),
...require("./variaveisComuns"), ...require("./variaveisComuns")
...require("./zCoordenadas"),
...require("./zDocumento"),
...require("./zodCustomizados")
}); });

View file

@ -97,7 +97,9 @@ class TipagemRotas {
let queryObj = Object.fromEntries(query.entries()); let queryObj = Object.fromEntries(query.entries());
const hash = url.hash; const hash = url.hash;
if (hash) { if (hash) {
const hashObj = Object.fromEntries(new URLSearchParams(hash.slice(1)).entries()); const hashObj = Object.fromEntries(
new URLSearchParams(hash.slice(1)).entries()
);
queryObj = { ...queryObj, ...hashObj }; queryObj = { ...queryObj, ...hashObj };
} }
for (const chave in queryObj) { for (const chave in queryObj) {

View file

@ -0,0 +1,72 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var tipoFiltro_26_exports = {};
__export(tipoFiltro_26_exports, {
agrupadores26: () => agrupadores26,
criarFiltro26: () => criarFiltro26,
operadores26: () => operadores26,
zFiltro26: () => zFiltro26
});
module.exports = __toCommonJS(tipoFiltro_26_exports);
var import_zod = require("zod");
var operadores26 = /* @__PURE__ */ ((operadores262) => {
operadores262["="] = "=";
operadores262["!="] = "!=";
operadores262[">"] = ">";
operadores262[">="] = ">=";
operadores262["<"] = "<";
operadores262["<="] = "<=";
operadores262["like"] = "like";
operadores262["in"] = "in";
return operadores262;
})(operadores26 || {});
var agrupadores26 = /* @__PURE__ */ ((agrupadores262) => {
agrupadores262["E"] = "E";
agrupadores262["OU"] = "OU";
return agrupadores262;
})(agrupadores26 || {});
const zOperadores = import_zod.z.nativeEnum(operadores26);
const zValor = import_zod.z.any();
const zCondicao = import_zod.z.record(zOperadores, zValor);
const zFiltro26 = import_zod.z.lazy(
() => import_zod.z.object({
E: import_zod.z.array(zFiltro26).optional(),
OU: import_zod.z.array(zFiltro26).optional()
}).catchall(import_zod.z.union([zCondicao, zFiltro26]))
);
const criarFiltro26 = (filtro) => filtro;
const _filtro = criarFiltro26({
idade: { [">=" /* >= */]: 18 },
["OU" /* OU */]: [
{ nome: { ["like" /* like */]: "%pa%" } },
{
["E" /* E */]: [
{ carro: { ano: { ["=" /* = */]: 2020 } } },
{ carro: { modelo: { ["in" /* in */]: ["Civic", "Corolla"] } } }
]
}
]
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
agrupadores26,
criarFiltro26,
operadores26,
zFiltro26
});

View file

@ -25,143 +25,22 @@ __export(uuid_exports, {
validarUuid: () => validarUuid validarUuid: () => validarUuid
}); });
module.exports = __toCommonJS(uuid_exports); module.exports = __toCommonJS(uuid_exports);
var import_uuid = require("uuid");
const erUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const erUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const validarUuid = (uuid2) => { const validarUuid = (uuid2) => {
return erUuid.test(String(uuid2 || "")); const retorno = erUuid.test(String(uuid2 || ""));
}; return retorno;
const uuidV4 = () => globalThis.crypto.randomUUID();
const uuid = uuidV4;
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
const rotL = (x, n) => x << n | x >>> 32 - n;
const md5 = (str) => {
const msg = new TextEncoder().encode(str);
const len = msg.length;
const bits = len * 8;
const padLen = len % 64 < 56 ? 56 - len % 64 : 120 - len % 64;
const padded = new Uint8Array(len + padLen + 8);
padded.set(msg);
padded[len] = 128;
const dv = new DataView(padded.buffer);
dv.setUint32(len + padLen, bits >>> 0, true);
dv.setUint32(len + padLen + 4, Math.floor(bits / 2 ** 32), true);
const T = Array.from(
{ length: 64 },
(_, i) => Math.abs(Math.sin(i + 1)) * 2 ** 32 >>> 0
);
const S = [
7,
12,
17,
22,
7,
12,
17,
22,
7,
12,
17,
22,
7,
12,
17,
22,
5,
9,
14,
20,
5,
9,
14,
20,
5,
9,
14,
20,
5,
9,
14,
20,
4,
11,
16,
23,
4,
11,
16,
23,
4,
11,
16,
23,
4,
11,
16,
23,
6,
10,
15,
21,
6,
10,
15,
21,
6,
10,
15,
21,
6,
10,
15,
21
];
let a0 = 1732584193, b0 = 4023233417, c0 = 2562383102, d0 = 271733878;
for (let off = 0; off < padded.length; off += 64) {
const M = [];
for (let j = 0; j < 16; j++) M[j] = dv.getUint32(off + j * 4, true);
let [A, B, C, D] = [a0, b0, c0, d0];
for (let i = 0; i < 64; i++) {
let F, g;
if (i < 16) {
F = B & C | ~B & D;
g = i;
} else if (i < 32) {
F = D & B | ~D & C;
g = (5 * i + 1) % 16;
} else if (i < 48) {
F = B ^ C ^ D;
g = (3 * i + 5) % 16;
} else {
F = C ^ (B | ~D);
g = 7 * i % 16;
}
F = F + A + T[i] + M[g] >>> 0;
A = D;
D = C;
C = B;
B = B + rotL(F, S[i]) >>> 0;
}
a0 = a0 + A >>> 0;
b0 = b0 + B >>> 0;
c0 = c0 + C >>> 0;
d0 = d0 + D >>> 0;
}
const toHexLE = (n) => {
let s = "";
for (let i = 0; i < 4; i++) s += (n >>> i * 8 & 255).toString(16).padStart(2, "0");
return s;
};
return toHexLE(a0) + toHexLE(b0) + toHexLE(c0) + toHexLE(d0);
};
const formatarUuidV3 = (hash) => {
const c = hash.slice(0, 32);
const v = (Number.parseInt(c[16], 16) & 3 | 8).toString(16);
return `${c.slice(0, 8)}-${c.slice(8, 12)}-3${c.slice(13, 16)}-${v}${c.slice(17, 20)}-${c.slice(20, 32)}`;
}; };
const uuidV3 = (chave, grupo) => { const uuidV3 = (chave, grupo) => {
const namespace = grupo ? uuidV3(grupo) : NIL_UUID; return (0, import_uuid.v3)(
const input = typeof chave === "string" ? chave : typeof chave === "number" ? String(chave) : JSON.stringify(chave); // Converte a chave para string (de forma segura)
return formatarUuidV3(md5(namespace + input)); typeof chave === "string" ? chave : typeof chave === "number" ? String(chave) : JSON.stringify(chave),
// Se um grupo foi fornecido, gera um UUID v3 recursivamente com base nele, senão usa NIL
grupo ? uuidV3(grupo) : import_uuid.NIL
);
}; };
const uuidV4 = import_uuid.v4;
const uuid = uuidV4;
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = { 0 && (module.exports = {
erUuid, erUuid,

View file

@ -22,7 +22,9 @@ __export(variaveisComuns_exports, {
nomeVariavel: () => nomeVariavel nomeVariavel: () => nomeVariavel
}); });
module.exports = __toCommonJS(variaveisComuns_exports); module.exports = __toCommonJS(variaveisComuns_exports);
const esperar = (ms) => new Promise((resolve) => setTimeout(() => resolve(true), ms)); const esperar = (ms) => new Promise(
(resolve) => setTimeout(() => resolve(true), ms)
);
const nomeVariavel = (v) => Object.keys(v).join("/"); const nomeVariavel = (v) => Object.keys(v).join("/");
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = { 0 && (module.exports = {

View file

@ -1,44 +0,0 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var zCoordenadas_exports = {};
__export(zCoordenadas_exports, {
zCoordenadas: () => zCoordenadas
});
module.exports = __toCommonJS(zCoordenadas_exports);
var import_zod = __toESM(require("zod"));
const zCoordenadas = import_zod.default.object({
formato: import_zod.default.literal("decimal").default("decimal"),
datum: import_zod.default.literal("EPSG:4326").default("EPSG:4326"),
latitude: import_zod.default.number(),
longitude: import_zod.default.number()
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
zCoordenadas
});

View file

@ -1,48 +0,0 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var zDocumento_exports = {};
__export(zDocumento_exports, {
zDocCnpj: () => zDocCnpj,
zDocCpf: () => zDocCpf,
zDocumento: () => zDocumento
});
module.exports = __toCommonJS(zDocumento_exports);
var import_zod = __toESM(require("zod"));
const regexCnpjNumerico = /^\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}$/;
const regexCnpjAlfanumerico = /^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}\/[A-Z0-9]{4}-\d{2}$/i;
const yyyymm = Number((/* @__PURE__ */ new Date()).toISOString().slice(0, 7).replace("-", ""));
const zDocCnpj = import_zod.default.string().regex(yyyymm < 202407 ? regexCnpjNumerico : regexCnpjAlfanumerico).describe("Documento (CNPJ) no formato XX.XXX.XXX/XXXX-XX");
const zDocCpf = import_zod.default.string().regex(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/).describe("Documento (CPF) no formato XXX.XXX.XXX-XX");
const zDocumento = zDocCpf.or(zDocCnpj).describe("CPF ou CNPJ");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
zDocCnpj,
zDocCpf,
zDocumento
});

View file

@ -1,56 +0,0 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var zodCustomizados_exports = {};
__export(zodCustomizados_exports, {
zNumero: () => zNumero,
zNumeroInteiro: () => zNumeroInteiro,
zNumeroPositivo: () => zNumeroPositivo
});
module.exports = __toCommonJS(zodCustomizados_exports);
var import_zod = __toESM(require("zod"));
const zPreprocessarNumero = (p) => {
if (typeof p === "number") return p;
if (typeof p !== "string") return p;
let p2 = p;
if (p2.includes(",")) {
p2 = p2.replace(/\./g, "").replace(",", ".");
}
p2 = p2.replace(/[^0-9.]/g, "");
if (p2 == "") return null;
return Number(p2);
};
const zNumero = import_zod.default.preprocess(zPreprocessarNumero, import_zod.default.number());
const zNumeroPositivo = import_zod.default.preprocess(zPreprocessarNumero, import_zod.default.number().positive());
const zNumeroInteiro = import_zod.default.preprocess(zPreprocessarNumero, import_zod.default.number().int());
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
zNumero,
zNumeroInteiro,
zNumeroPositivo
});

View file

@ -1,40 +1,10 @@
import z from 'zod'; import z, { z as z$1 } from 'zod';
import _dayjs from 'dayjs'; import dayjs from 'dayjs';
export { Dayjs, ManipulateType } from 'dayjs'; export { Dayjs, ManipulateType } from 'dayjs';
import _duration from 'dayjs/plugin/duration'; import { v4 } from 'uuid';
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';
declare const aleatorio: (tamanho?: number) => string; declare const aleatorio: (tamanho?: number) => string;
type TipoPayloadAuditoria = {
/** UUID do registro de auditoria */
codigo?: string | null;
/** UUID do usuario da acao (pode ser null se for processo do sistema que não registrou) */
usuario_criacao: string | null;
/** Timestamp ou data de criacao / execucao */
data_criacao: string | Date;
/** Nome exato da tabela no banco que originou o registro */
tabela_origem: string;
/** Código único (UUID) do registro na tabela original */
codigo_origem: string;
/** JSON contendo o snapshot das colunas novas / editadas */
novo: Record<string, any>;
/** JSON contendo o snapshot das colunas antes da edição */
anterior: Record<string, any>;
/** Hash ou controle de versao do item, usualmente preenchido por new.ver_seg */
__versao: string;
/** Tipo de operação que gerou a auditoria */
acao: "criar" | "atualizar" | "deletar" | string;
/** Versão do sistema no momento em que a ação ocorreu */
versao_sistema: string;
};
/** gerar uma função de cache para uso em memoria */ /** gerar uma função de cache para uso em memoria */
declare const cacheM: <T>(chave: any, valor?: T, validadeSeg?: number) => T | undefined; declare const cacheM: <T>(chave: any, valor?: T, validadeSeg?: number) => T | undefined;
declare const verCacheM: () => { declare const verCacheM: () => {
@ -77,8 +47,7 @@ declare enum operadores {
"<=" = "<=", "<=" = "<=",
like = "like", like = "like",
in = "in", in = "in",
isNull = "isNull", isNull = "isNull"
notIn = "notIn"
} }
type tipoFiltro = { type tipoFiltro = {
coluna: string; coluna: string;
@ -106,7 +75,6 @@ declare const zOperadores: z.ZodEnum<{
like: "like"; like: "like";
in: "in"; in: "in";
isNull: "isNull"; isNull: "isNull";
notIn: "notIn";
}>; }>;
declare const zFiltro: z.ZodObject<{ declare const zFiltro: z.ZodObject<{
coluna: z.ZodString; coluna: z.ZodString;
@ -121,186 +89,14 @@ declare const zFiltro: z.ZodObject<{
like: "like"; like: "like";
in: "in"; in: "in";
isNull: "isNull"; isNull: "isNull";
notIn: "notIn";
}>; }>;
ou: z.ZodOptional<z.ZodBoolean>; ou: z.ZodOptional<z.ZodBoolean>;
}, z.core.$strip>; }, z.core.$strip>;
/** declare const definirDayjsbr: (dayjsEntrada: typeof dayjs) => typeof dayjs;
* 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.
*/
/**
* 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 { iniciarDayjsBr } from "p-comuns"
* import "dayjs/locale/pt-br" // Importante: importar o locale!
* export const dayjsbr = iniciarDayjsBr({
* dayjs,
* duration,
* isSameOrAfter,
* isSameOrBefore,
* minMax,
* relativeTime,
* timezone,
* utc,
* weekOfYear,
* })
* ```
*/
declare const iniciarDayjsBr: ({ 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;
}) => typeof _dayjs;
/**
* @deprecated Use iniciarDayjsBr em vez de definirDayjsBr. O método defineDayjsBr está obsoleto e será removido em futuras versões.
*/
declare 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;
}) => typeof _dayjs;
declare const link_paiol = "https://paiol.idz.one"; declare const link_paiol = "https://paiol.idz.one";
/** Níveis de severidade para o sistema de log estruturado. */
declare enum NivelLog {
/** O mais baixo nível, ideal para rastreamento detalhado de fluxo e execução. */
RASTREAMENTO = "RASTREAMENTO",
/** Usado para informações que ajudam a entender o estado do sistema durante a execução. */
DEPURACAO = "DEPURACAO",
/** Informações gerais e eventos do sistema. */
INFORMACAO = "INFORMACAO",
/** Eventos inesperados, mas que não impedem o funcionamento do sistema. */
AVISO = "AVISO",
/** Erros que impactam o funcionamento do sistema, mas que podem ser recuperados. */
ERRO = "ERRO",
/** O nível mais alto de severidade, indicando falhas que requerem atenção imediata. */
CRITICO = "CRITICO"
}
type DetalheNivel = {
peso: number;
rotulo: string;
emoji: string;
metodo: "debug" | "info" | "warn" | "error";
};
/** Detalhes de cada nível de log — peso para filtragem, emoji e método do console. */
declare const NivelLogDetalhes: Record<NivelLog, DetalheNivel>;
/** Estrutura de uma entrada de log emitida pelo sistema. */
type EntradaLog = {
timestamp: string;
nivel: keyof typeof NivelLog;
/** Identificador da aplicação/instância (ex: "front:e-licencie:12345"). */
app: string;
/** Local no código de onde o log foi emitido (ex: "criarUsuario()"). */
origem: string;
mensagem: string;
dados?: unknown;
};
/** Interface pública do logger retornado por `iniciarELog`. */
type ELogger = {
rastreamento: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
depuracao: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
info: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
aviso: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
erro: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
critico: (pr: {
origem: string;
mensagem: string;
dados?: unknown;
}) => void;
};
/** Opções de configuração do logger, disponíveis no callback de arquivamento. */
type OpoesELogger = {
app: string;
nivelMinimo: keyof typeof NivelLog;
};
/** Tipo do callback de arquivamento de logs. */
type ArquivamentoLog = (entrada: EntradaLog, opcoes: OpoesELogger) => void;
/**
* Inicializa o sistema de log estruturado.
*
* @param opcoes.app - Identificador da aplicação/instância (ex: `"front:e-licencie:12345"`)
* @param opcoes.nivelMinimo - Nível mínimo para exibição no console (padrão: INFORMACAO)
* @param opcoes.arquivamento - Callback opcional para persistir/enviar as entradas de log
*
* @example
* ```ts
* const log = iniciarELog({ app: "front:e-licencie:12345" })
*
* log.info({ origem: "criarUsuario()", mensagem: "Usuário criado", dados: { id: "abc-123" } })
* // → ℹ️ [Informação] [front:e-licencie:12345] [criarUsuario()] Usuário criado
* ```
*/
declare const iniciarELog: (opcoes: {
app: string;
nivelMinimo?: keyof typeof NivelLog;
arquivamento?: ArquivamentoLog;
}) => ELogger;
type tiposArquivo = "imagem" | "documento" | "vídeo" | "outros"; type tiposArquivo = "imagem" | "documento" | "vídeo" | "outros";
declare const extensoes: { declare const extensoes: {
ext: string; ext: string;
@ -314,141 +110,6 @@ declare const extensoes: {
*/ */
declare const tipoArquivo: (nomeArquivo: string | null | undefined) => tiposArquivo; declare const tipoArquivo: (nomeArquivo: string | null | undefined) => tiposArquivo;
/**
* =============================================================================
* FILTRO DELTA (zFiltroDelta)
* =============================================================================
*
* OBJETIVO
* -----------------------------------------------------------------------------
* Novo sistema de filtros projetado para maior flexibilidade e geração segura
* de instruções SQL dinâmicas (WHERE).
*
* REGRAS IMPORTANTES (PARA IA)
* -----------------------------------------------------------------------------
* - O filtro é composto de duas partes obrigatórias: `condicoes` e `formula`.
* - Apenas referências aos `id`s das `condicoes` podem ser usadas na `formula`.
* - Não use sintaxe baseada em objetos aninhados para agrupamento (ex: { E: [], OU: [] }). Use fórmulas em string.
*
* 1) CONDIÇÕES (`condicoes`):
* Array de objetos contendo as definições isoladas de cada comparação.
* Exemplo:
* [
* { id: "{1}", coluna: "idade", operador: ">=", valor: 18 },
* { id: "{2}", coluna: "nome", operador: "like", valor: "%pa%" }
* ]
* - `id`: Deve SEMPRE seguir o formato {identificador}. Ex: `{c1}`, `{idade_min}`.
* - `coluna`: O nome da coluna ou um path JSONB válido (ex: `veiculo.ano`).
* - `operador`: Um dos valores do tipo `tipoOperadorFiltroDelta` (veja a constante).
*
* 2) FÓRMULA (`formula`):
* String que define a expressão lógica relacionando as condições através de seus `id`s.
* Operadores Lógicos Suportados (EM MAIÚSCULO):
* - `E` (AND)
* - `OU` (OR)
* - `NAO` (NOT)
* Suporta o agrupamento lógico usando parênteses `()`
* Exemplo válido: "({1} E NAO({2})) OU {3}"
*
* =============================================================================
*/
/**
* Operadores permitidos para comparação.
*/
declare const zOperadorFiltroDelta: z.ZodEnum<{
"=": "=";
"!=": "!=";
">": ">";
">=": ">=";
"<": "<";
"<=": "<=";
like: "like";
in: "in";
"\u2229": "∩";
}>;
declare const operadorFiltroDeltaDetalhes: Record<z.infer<typeof zOperadorFiltroDelta>, {
rotulo: string;
descricao: string;
}>;
/**
* Coluna simples ou caminho aninhado de jsonb.
*/
declare const zColunaFiltroDelta: z.ZodString;
/**
* Estrutura individual de uma condição do filtro.
*/
declare const zCondicaoFiltroDelta: z.ZodObject<{
id: z.ZodString;
coluna: z.ZodString;
operador: z.ZodEnum<{
"=": "=";
"!=": "!=";
">": ">";
">=": ">=";
"<": "<";
"<=": "<=";
like: "like";
in: "in";
"\u2229": "∩";
}>;
valor: z.ZodAny;
}, z.core.$strip>;
/**
* Estrutura principal do filtro delta.
*/
declare const zFiltroDelta: z.ZodObject<{
condicoes: z.ZodArray<z.ZodObject<{
id: z.ZodString;
coluna: z.ZodString;
operador: z.ZodEnum<{
"=": "=";
"!=": "!=";
">": ">";
">=": ">=";
"<": "<";
"<=": "<=";
like: "like";
in: "in";
"\u2229": "∩";
}>;
valor: z.ZodAny;
}, z.core.$strip>>;
formula: z.ZodString;
}, z.core.$strip>;
type tipoOperadorFiltroDelta = z.infer<typeof zOperadorFiltroDelta>;
type tipoColunaFiltroDelta = z.infer<typeof zColunaFiltroDelta>;
type tipoCondicaoFiltroDelta = z.infer<typeof zCondicaoFiltroDelta>;
type tipoFiltroDelta = z.infer<typeof zFiltroDelta>;
type tipoCondicaoFiltroDeltaTipado<T extends string> = tipoCondicaoFiltroDelta & {
coluna: T;
};
type tipoFiltroDeltaColunaTipada<T extends string> = {
condicoes: tipoCondicaoFiltroDeltaTipado<T>[];
formula: string;
};
declare const criarFiltroDelta: <T extends string>(filtro: tipoFiltroDeltaColunaTipada<T>) => tipoFiltroDeltaColunaTipada<T>;
/**
* Fábrica para criar filtros com colunas estritamente tipadas.
* Útil para autocompletar os nomes das colunas e garantir a estrutura no TypeScript.
*
* @example
* ```ts
* const { criarFiltroDelta } = iniciarFiltroDelta<"nome" | "idade" | "jsonb.propriedade">()
*
* const filtro = criarFiltroDelta({
* condicoes: [
* { id: "{c1}", coluna: "idade", operador: ">", valor: 18 },
* { id: "{c2}", coluna: "nome", operador: "=", valor: "luiz" },
* { id: "{c3}", coluna: "jsonb.propriedade", operador: "=", valor: "valor" },
* ],
* formula: "({c1} E {c2}) OU {c3}",
* })
* ```
*/
declare const iniciarFiltroDelta: <TColunas extends string>() => {
criarFiltroDelta: (filtro: tipoFiltroDeltaColunaTipada<TColunas>) => tipoFiltroDeltaColunaTipada<TColunas>;
};
/** /**
* LocalStorage Tipado * LocalStorage Tipado
* Lê ou grava um valor no localStorage, mantendo o tipo genérico <T>. * Lê ou grava um valor no localStorage, mantendo o tipo genérico <T>.
@ -593,6 +254,151 @@ declare class TipagemRotas<T extends {
parametros(urlEntrada?: string): Partial<T>; parametros(urlEntrada?: string): Partial<T>;
} }
/**
* =============================================================================
* 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.
*
* =============================================================================
*/
declare enum operadores26 {
"=" = "=",
"!=" = "!=",
">" = ">",
">=" = ">=",
"<" = "<",
"<=" = "<=",
like = "like",
in = "in"
}
declare 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[];
};
type PgOpsFor<V> = V extends number ? PgOpsNumber : V extends string ? PgOpsString : V extends boolean ? PgOpsBoolean : never;
type IsPlainObject<T> = T extends object ? T extends Function ? false : T extends readonly any[] ? false : true : false;
type FiltroCampos<T> = {
[K in keyof T]?: IsPlainObject<T[K]> extends true ? tipoFiltro26<T[K]> : PgOpsFor<T[K]>;
};
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>[];
};
declare const zFiltro26: z$1.ZodType<any>;
declare const criarFiltro26: <T>(filtro: tipoFiltro26<T>) => tipoFiltro26<T>;
/** /**
* Essa variável se conecta a tabela_lidades * Essa variável se conecta a tabela_lidades
* *
@ -619,26 +425,35 @@ declare const unidades_medida: {
/** /**
* Valida se uma string é um UUID válido (qualquer versão). * Valida se uma string é um UUID válido (qualquer versão).
*
* @param valor - A string que será validada.
* @returns booleano indicando se é um UUID válido.
*/ */
declare const erUuid: RegExp; declare const erUuid: RegExp;
declare const validarUuid: (uuid: string | number | undefined | null) => boolean; declare const validarUuid: (uuid: string | number | undefined | null) => boolean;
/**
* Gera um UUID v4 (aleatório, não determinístico).
* Usa `globalThis.crypto.randomUUID()` — disponível em Node 19+, Bun e browsers modernos.
*/
declare const uuidV4: () => string;
/**
* @deprecated Use uuidV4() diretamente.
*/
declare const uuid: () => string;
/** /**
* Gera um UUID determinístico (versão 3) com base em uma chave e um grupo (namespace). * Gera um UUID determinístico (versão 3) com base em uma chave e um grupo (namespace).
* Implementação pura JS (MD5), sem dependência de Node.js — funciona em browser e server.
* *
* @param chave - Valor a serializar (string, number ou objeto). * - Usa o algoritmo MD5 (RFC 4122).
* @param grupo - Namespace opcional; se omitido, usa UUID nil. * - Sempre retorna o mesmo UUID para a mesma combinação chave + grupo.
* - Caso o grupo não seja informado, usa o UUID "nil" como namespace.
*
* @param chave - Qualquer valor que será convertido em string para gerar o UUID (ex: número, string ou objeto).
* @param grupo - Opcional. Namespace para separar domínios diferentes de UUIDs.
* @returns UUID v3 (determinístico)
*/ */
declare const uuidV3: (chave: unknown, grupo?: unknown) => string; declare const uuidV3: (chave: any, grupo?: any) => string;
/**
* Gera um UUID v4 (aleatório, não determinístico).
*
* - Usado quando unicidade é necessária, mas não se exige que seja previsível.
*/
declare const uuidV4: typeof v4;
/**
* @deprecated Esta variável será descontinuada em versões futuras.
* Use a função `uuidV4()` diretamente.
*/
declare const uuid: typeof v4;
declare const esperar: (ms: number) => Promise<true>; declare const esperar: (ms: number) => Promise<true>;
/** /**
@ -652,37 +467,4 @@ declare const nomeVariavel: (v: {
[key: string]: any; [key: string]: any;
}) => string; }) => string;
/** export { Produtos, TipagemRotas, agrupadores26, aleatorio, cacheM, cacheMFixo, cacheMemoria, camposComuns, criarFiltro26, definirDayjsbr, erUuid, esperar, extensoes, type interfaceConsulta, link_paiol, localValor, nomeVariavel, objetoPg, operadores, operadores26, paraObjetoRegistroPg, pgObjeto, siglas_unidades_medida, texto_busca, tipoArquivo, type tipoFiltro, type tipoFiltro26, tipoUsuarioResiduos, tiposSituacoesElicencie, tx, umaFuncao, umaVariavel, unidades_medida, uuid, uuidV3, uuidV4, uuid_null, validarUuid, verCacheM, zFiltro, zFiltro26, zOperadores };
* No futuro podemos melhorar este Zod para incluir mais formatos de coordenadas.
*
*/
declare const zCoordenadas: z.ZodObject<{
formato: z.ZodDefault<z.ZodLiteral<"decimal">>;
datum: z.ZodDefault<z.ZodLiteral<"EPSG:4326">>;
latitude: z.ZodNumber;
longitude: z.ZodNumber;
}, z.core.$strip>;
declare const zDocCnpj: z.ZodString;
declare const zDocCpf: z.ZodString;
declare const zDocumento: z.ZodUnion<[z.ZodString, z.ZodString]>;
/**
* Schema numérico que aceita strings legadas e normaliza para `number`.
*
* O campo **é** um número. O `preprocess` resolve compatibilidade com dados
* antigos onde o frontend enviava strings formatadas (BR ou monetária).
*
* Formatos de entrada aceitos:
* - `10` → number direto
* - `10.1` → ponto decimal
* - `10,1` → vírgula decimal (BR)
* - `1.000,1` → milhar com ponto + vírgula decimal (BR)
* - `R$ 10,01` → prefixo monetário legado
*/
declare const zNumero: z.ZodPreprocess<z.ZodNumber>;
declare const zNumeroPositivo: z.ZodPreprocess<z.ZodNumber>;
declare const zNumeroInteiro: z.ZodPreprocess<z.ZodNumber>;
export { type ArquivamentoLog, type ELogger, type EntradaLog, NivelLog, NivelLogDetalhes, type OpoesELogger, Produtos, TipagemRotas, type TipoPayloadAuditoria, aleatorio, cacheM, cacheMFixo, cacheMemoria, camposComuns, criarFiltroDelta, defineDayjsBr, erUuid, esperar, extensoes, iniciarDayjsBr, iniciarELog, iniciarFiltroDelta, type interfaceConsulta, link_paiol, localValor, nomeVariavel, objetoPg, operadorFiltroDeltaDetalhes, operadores, paraObjetoRegistroPg, pgObjeto, siglas_unidades_medida, texto_busca, tipoArquivo, type tipoColunaFiltroDelta, type tipoCondicaoFiltroDelta, type tipoCondicaoFiltroDeltaTipado, type tipoFiltro, type tipoFiltroDelta, type tipoFiltroDeltaColunaTipada, type tipoOperadorFiltroDelta, tipoUsuarioResiduos, tiposSituacoesElicencie, tx, umaFuncao, umaVariavel, unidades_medida, uuid, uuidV3, uuidV4, uuid_null, validarUuid, verCacheM, zColunaFiltroDelta, zCondicaoFiltroDelta, zCoordenadas, zDocCnpj, zDocCpf, zDocumento, zFiltro, zFiltroDelta, zNumero, zNumeroInteiro, zNumeroPositivo, zOperadorFiltroDelta, zOperadores };

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{ {
"name": "p-comuns", "name": "p-comuns",
"version": "0.355.0", "version": "0.314.0",
"description": "", "description": "",
"main": "./dist-front/index.mjs", "main": "./dist-front/index.mjs",
"module": "./dist-front/index.mjs", "module": "./dist-front/index.mjs",
@ -17,8 +17,7 @@
"check": "pnpm run biome && npx tsc --noEmit", "check": "pnpm run biome && npx tsc --noEmit",
"build": "npm --no-git-tag-version version minor && pnpm run biome && tsup --config ./tsup/tsup.config.ts && pnpm run pacote", "build": "npm --no-git-tag-version version minor && pnpm run biome && tsup --config ./tsup/tsup.config.ts && pnpm run pacote",
"teste": "npx vitest run src/testes/TipagemRotas.test.ts", "teste": "npx vitest run src/testes/TipagemRotas.test.ts",
"pacote": "npm pack && npm pack && mv $(npm pack --silent) pacote.tgz", "pacote": "npm pack && npm pack && mv $(npm pack --silent) pacote.tgz"
"postinstall": "node ./scripts/atualizar-biome.js"
}, },
"author": { "author": {
"name": "AZTECA SOFTWARE LTDA", "name": "AZTECA SOFTWARE LTDA",
@ -28,19 +27,21 @@
"license": "ISC", "license": "ISC",
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"cross-fetch": "4.1.0",
"uuid": "^11.1.0", "uuid": "^11.1.0",
"zod": "4.4.3", "zod": "4.1.4",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"@biomejs/biome": "2.4.12", "@biomejs/biome": "2.4.0",
"@types/node": "^22", "@types/node": "^20.19.22",
"tsup": "8.5.1", "tsup": "8.5.0",
"typescript": "^6", "typescript": "~5.9.3",
"unbuild": "^3.6.1", "unbuild": "^3.6.1",
"vitest": "^3.2.4" "vitest": "^3.2.4"
}, },
"peerDependencies": { "peerDependencies": {
"cross-fetch": "4.1.0",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"uuid": "^11.1.0", "uuid": "^11.1.0",
"zod": "4.4.3" "zod": "4.1.4"
} }
} }

Binary file not shown.

1950
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,96 +0,0 @@
const fs = require('node:fs');
const path = require('node:path');
const initCwd = process.env.INIT_CWD;
// Se não tiver INIT_CWD, não foi chamado pelo npm/pnpm install
if (!initCwd) {
process.exit(0);
}
// O próprio p-comuns não precisa se atualizar na sua pasta interna
if (initCwd === process.cwd()) {
process.exit(0);
}
const me = require('../package.json');
const biomeVersion = me.devDependencies && me.devDependencies['@biomejs/biome'];
if (!biomeVersion) {
process.exit(0);
}
/**
* Lê os arquivos do diretório em busca de package.json
*/
function findPackageJson(dir) {
let results = [];
try {
const list = fs.readdirSync(dir);
for (const file of list) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat && stat.isDirectory()) {
// Ignora pastas que não devemos varrer
if (
![
'node_modules',
'.git',
'dist',
'build',
'.nuxt',
'.output',
'.vscode',
'.idea',
].includes(file)
) {
results = results.concat(findPackageJson(filePath));
}
} else if (file === 'package.json') {
results.push(filePath);
}
}
} catch (err) {
// ignora pastas sem acesso
}
return results;
}
const files = findPackageJson(initCwd);
let updated = 0;
for (const file of files) {
try {
const content = fs.readFileSync(file, 'utf8');
// Detecta se usa tab ou espaço
const indent = content.match(/^[ \t]+/m) ? content.match(/^[ \t]+/m)[0] : '\t';
const json = JSON.parse(content);
let changed = false;
const updateDeps = (tipo) => {
if (json[tipo] && json[tipo]['@biomejs/biome']) {
if (json[tipo]['@biomejs/biome'] !== biomeVersion) {
json[tipo]['@biomejs/biome'] = biomeVersion;
changed = true;
}
}
};
updateDeps('dependencies');
updateDeps('devDependencies');
updateDeps('peerDependencies');
if (changed) {
fs.writeFileSync(file, JSON.stringify(json, null, indent) + '\n', 'utf8');
updated++;
console.log(`[p-comuns] @biomejs/biome atualizado para ${biomeVersion} em: ${path.relative(initCwd, file)}`);
}
} catch (e) {
console.error(`[p-comuns] Erro ao atualizar ${file}: ${e.message}`);
}
}
if (updated > 0) {
console.log(`[p-comuns] Total de package.json atualizados: ${updated}`);
}

View file

@ -1,31 +0,0 @@
export type TipoPayloadAuditoria = {
/** UUID do registro de auditoria */
codigo?: string | null
/** UUID do usuario da acao (pode ser null se for processo do sistema que não registrou) */
usuario_criacao: string | null
/** Timestamp ou data de criacao / execucao */
data_criacao: string | Date
/** Nome exato da tabela no banco que originou o registro */
tabela_origem: string
/** Código único (UUID) do registro na tabela original */
codigo_origem: string
/** JSON contendo o snapshot das colunas novas / editadas */
novo: Record<string, any>
/** JSON contendo o snapshot das colunas antes da edição */
anterior: Record<string, any>
/** Hash ou controle de versao do item, usualmente preenchido por new.ver_seg */
__versao: string
/** Tipo de operação que gerou a auditoria */
acao: "criar" | "atualizar" | "deletar" | string
/** Versão do sistema no momento em que a ação ocorreu */
versao_sistema: string
}

View file

@ -12,7 +12,11 @@ const _cache: {
;(globalThis as any).cacheMemoria_cache = _cache ;(globalThis as any).cacheMemoria_cache = _cache
export const cacheM = <T>(chave: any, valor?: T, validadeSeg?: number): T | undefined => { export const cacheM = <T>(
chave: any,
valor?: T,
validadeSeg?: number,
): T | undefined => {
// converte a chave e string // converte a chave e string
const txChave: string = const txChave: string =
typeof chave == "string" typeof chave == "string"

View file

@ -10,7 +10,6 @@ export enum operadores {
like = "like", like = "like",
in = "in", in = "in",
isNull = "isNull", isNull = "isNull",
notIn = "notIn",
} }
export type tipoFiltro = { export type tipoFiltro = {
@ -41,7 +40,6 @@ export const zOperadores = z.enum([
"like", "like",
"in", "in",
"isNull", "isNull",
"notIn",
]) ])
export const zFiltro = z.object({ export const zFiltro = z.object({

View file

@ -1,110 +0,0 @@
/**
* 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 { iniciarDayjsBr } from "p-comuns"
* import "dayjs/locale/pt-br" // Importante: importar o locale!
* export const dayjsbr = iniciarDayjsBr({
* dayjs,
* duration,
* isSameOrAfter,
* isSameOrBefore,
* minMax,
* relativeTime,
* timezone,
* utc,
* weekOfYear,
* })
* ```
*/
const iniciarDayjsBr = ({
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
}
/**
* @deprecated Use iniciarDayjsBr em vez de definirDayjsBr. O método defineDayjsBr está obsoleto e será removido em futuras versões.
*/
const defineDayjsBr = iniciarDayjsBr
export type { Dayjs }
export { defineDayjsBr, iniciarDayjsBr }

View file

@ -1,132 +0,0 @@
/** Níveis de severidade para o sistema de log estruturado. */
export enum NivelLog {
/** O mais baixo nível, ideal para rastreamento detalhado de fluxo e execução. */
RASTREAMENTO = "RASTREAMENTO",
/** Usado para informações que ajudam a entender o estado do sistema durante a execução. */
DEPURACAO = "DEPURACAO",
/** Informações gerais e eventos do sistema. */
INFORMACAO = "INFORMACAO",
/** Eventos inesperados, mas que não impedem o funcionamento do sistema. */
AVISO = "AVISO",
/** Erros que impactam o funcionamento do sistema, mas que podem ser recuperados. */
ERRO = "ERRO",
/** O nível mais alto de severidade, indicando falhas que requerem atenção imediata. */
CRITICO = "CRITICO",
}
type DetalheNivel = {
peso: number
rotulo: string
emoji: string
metodo: "debug" | "info" | "warn" | "error"
}
/** Detalhes de cada nível de log — peso para filtragem, emoji e método do console. */
export const NivelLogDetalhes: Record<NivelLog, DetalheNivel> = {
[NivelLog.RASTREAMENTO]: { peso: 1, rotulo: "Rastreamento", emoji: "🔍", metodo: "debug" },
[NivelLog.DEPURACAO]: { peso: 2, rotulo: "Depuração", emoji: "🐛", metodo: "debug" },
[NivelLog.INFORMACAO]: { peso: 3, rotulo: "Informação", emoji: "ℹ️", metodo: "info" },
[NivelLog.AVISO]: { peso: 4, rotulo: "Aviso", emoji: "⚠️", metodo: "warn" },
[NivelLog.ERRO]: { peso: 5, rotulo: "Erro", emoji: "❌", metodo: "error" },
[NivelLog.CRITICO]: { peso: 6, rotulo: "Crítico", emoji: "🔥", metodo: "error" },
}
/** Estrutura de uma entrada de log emitida pelo sistema. */
export type EntradaLog = {
timestamp: string
nivel: keyof typeof NivelLog
/** Identificador da aplicação/instância (ex: "front:e-licencie:12345"). */
app: string
/** Local no código de onde o log foi emitido (ex: "criarUsuario()"). */
origem: string
mensagem: string
dados?: unknown
}
/** Interface pública do logger retornado por `iniciarELog`. */
export type ELogger = {
rastreamento: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
depuracao: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
info: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
aviso: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
erro: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
critico: (pr: { origem: string; mensagem: string; dados?: unknown }) => void
}
/** Opções de configuração do logger, disponíveis no callback de arquivamento. */
export type OpoesELogger = {
app: string
nivelMinimo: keyof typeof NivelLog
}
/** Tipo do callback de arquivamento de logs. */
export type ArquivamentoLog = (entrada: EntradaLog, opcoes: OpoesELogger) => void
/**
* Inicializa o sistema de log estruturado.
*
* @param opcoes.app - Identificador da aplicação/instância (ex: `"front:e-licencie:12345"`)
* @param opcoes.nivelMinimo - Nível mínimo para exibição no console (padrão: INFORMACAO)
* @param opcoes.arquivamento - Callback opcional para persistir/enviar as entradas de log
*
* @example
* ```ts
* const log = iniciarELog({ app: "front:e-licencie:12345" })
*
* log.info({ origem: "criarUsuario()", mensagem: "Usuário criado", dados: { id: "abc-123" } })
* // → ℹ️ [Informação] [front:e-licencie:12345] [criarUsuario()] Usuário criado
* ```
*/
export const iniciarELog = (opcoes: {
app: string
nivelMinimo?: keyof typeof NivelLog
arquivamento?: ArquivamentoLog
}): ELogger => {
const nivel: keyof typeof NivelLog = opcoes.nivelMinimo ?? NivelLog.INFORMACAO
const pesoMinimo = NivelLogDetalhes[nivel].peso
const emitir = (
nivelLog: keyof typeof NivelLog,
pr: { origem: string; mensagem: string; dados?: unknown },
) => {
const config = NivelLogDetalhes[nivelLog]
if (config.peso < pesoMinimo) return
const entrada: EntradaLog = {
timestamp: new Date().toISOString(),
nivel: nivelLog,
app: opcoes.app,
origem: pr.origem,
mensagem: pr.mensagem,
...(pr.dados !== undefined ? { dados: pr.dados } : {}),
}
console[config.metodo](
`${config.emoji} [${config.rotulo}] [${opcoes.app}] [${pr.origem}] ${pr.mensagem}`,
pr.dados !== undefined ? pr.dados : "",
)
if (opcoes.arquivamento) {
opcoes.arquivamento(entrada, { app: opcoes.app, nivelMinimo: nivel })
}
}
return {
rastreamento: (pr) => emitir(NivelLog.RASTREAMENTO, pr),
depuracao: (pr) => emitir(NivelLog.DEPURACAO, pr),
info: (pr) => emitir(NivelLog.INFORMACAO, pr),
aviso: (pr) => emitir(NivelLog.AVISO, pr),
erro: (pr) => emitir(NivelLog.ERRO, pr),
critico: (pr) => emitir(NivelLog.CRITICO, pr),
}
}
const _log = iniciarELog({
app: "testando",
nivelMinimo: NivelLog.INFORMACAO,
arquivamento: () => {
//
},
})
//log.aviso({ origem: "teste", mensagem: "teste" })

View file

@ -162,7 +162,9 @@ export const extensoes: {
* @param nomeArquivo * @param nomeArquivo
* @returns * @returns
*/ */
export const tipoArquivo = (nomeArquivo: string | null | undefined): tiposArquivo => { export const tipoArquivo = (
nomeArquivo: string | null | undefined,
): tiposArquivo => {
// extenssão do arquivo // extenssão do arquivo
const extArquivo = String(nomeArquivo || "") const extArquivo = String(nomeArquivo || "")
.toLocaleLowerCase() .toLocaleLowerCase()

View file

@ -1,279 +0,0 @@
import z from "zod"
/**
* =============================================================================
* FILTRO DELTA (zFiltroDelta)
* =============================================================================
*
* OBJETIVO
* -----------------------------------------------------------------------------
* Novo sistema de filtros projetado para maior flexibilidade e geração segura
* de instruções SQL dinâmicas (WHERE).
*
* REGRAS IMPORTANTES (PARA IA)
* -----------------------------------------------------------------------------
* - O filtro é composto de duas partes obrigatórias: `condicoes` e `formula`.
* - Apenas referências aos `id`s das `condicoes` podem ser usadas na `formula`.
* - Não use sintaxe baseada em objetos aninhados para agrupamento (ex: { E: [], OU: [] }). Use fórmulas em string.
*
* 1) CONDIÇÕES (`condicoes`):
* Array de objetos contendo as definições isoladas de cada comparação.
* Exemplo:
* [
* { id: "{1}", coluna: "idade", operador: ">=", valor: 18 },
* { id: "{2}", coluna: "nome", operador: "like", valor: "%pa%" }
* ]
* - `id`: Deve SEMPRE seguir o formato {identificador}. Ex: `{c1}`, `{idade_min}`.
* - `coluna`: O nome da coluna ou um path JSONB válido (ex: `veiculo.ano`).
* - `operador`: Um dos valores do tipo `tipoOperadorFiltroDelta` (veja a constante).
*
* 2) FÓRMULA (`formula`):
* String que define a expressão lógica relacionando as condições através de seus `id`s.
* Operadores Lógicos Suportados (EM MAIÚSCULO):
* - `E` (AND)
* - `OU` (OR)
* - `NAO` (NOT)
* Suporta o agrupamento lógico usando parênteses `()`
* Exemplo válido: "({1} E NAO({2})) OU {3}"
*
* =============================================================================
*/
/**
* Operadores permitidos para comparação.
*/
export const zOperadorFiltroDelta = z.enum([">", "<", ">=", "<=", "=", "!=", "in", "like", "∩"])
export const operadorFiltroDeltaDetalhes: Record<
z.infer<typeof zOperadorFiltroDelta>,
{ rotulo: string; descricao: string }
> = {
">": {
rotulo: "Maior que",
descricao: "O valor de A deve ser maior que o valor de B",
},
"<": {
rotulo: "Menor que",
descricao: "O valor de A deve ser menor que o valor de B",
},
">=": {
rotulo: "Maior ou igual a",
descricao: "O valor de A deve ser maior ou igual ao valor de B",
},
"<=": {
rotulo: "Menor ou igual a",
descricao: "O valor de A deve ser menor ou igual ao valor de B",
},
"=": {
rotulo: "Igual a",
descricao: "O valor de A deve ser igual ao valor de B",
},
"!=": {
rotulo: "Diferente de",
descricao: "O valor de A deve ser diferente do valor de B",
},
in: {
rotulo: "Está em",
descricao: "O valor de A deve estar presente na coleção ou lista definida em B",
},
like: {
rotulo: "Contém",
descricao: "O valor de A deve conter o texto informado em B",
},
"∩": {
rotulo: "Interseção",
descricao: "A e B devem possuir pelo menos um elemento em comum",
},
}
/**
* Valida o identificador da condição.
*
* Formato esperado:
* {identificador} ou {identificador:sufixo}
*/
const regexIdCondicaoFiltroDelta = /^\{[\w:]+\}$/
/**
* Valida nomes de colunas e caminhos jsonb.
*/
const regexColunaFiltroDelta = /^\w+(\.\w+)*$/
/**
* Coluna simples ou caminho aninhado de jsonb.
*/
export const zColunaFiltroDelta = z
.string()
.regex(regexColunaFiltroDelta, "Coluna inválida")
.describe("nome da coluna ou caminho aninhado do jsonb")
/**
* Estrutura individual de uma condição do filtro.
*/
export const zCondicaoFiltroDelta = z.object({
/**
* Identificador único da condição.
*
* Exemplo:
* {1}
*/
id: z
.string()
.describe("id da condição do filtro")
.regex(regexIdCondicaoFiltroDelta, "O id deve seguir o formato {identificador}"),
/**
* Nome da coluna ou caminho jsonb.
*/
coluna: zColunaFiltroDelta,
/**
* Operador da comparação.
*/
operador: zOperadorFiltroDelta,
/**
* Valor utilizado na comparação.
*/
valor: z.any().describe("valor de comparação"),
})
/**
* Verifica se a fórmula possui uma estrutura lógica válida.
*/
const formulaFiltroDeltaValida = (formula: string) => {
/**
* Extrai apenas os tokens permitidos:
* - referências de condição: {id} ou {id:sufixo}
* - operadores lógicos: E, OU
* - negação: NAO(...)
* - parênteses
*/
const tokensPermitidos = formula.match(/\{[\w:]+\}|\bNAO\b|\bE\b|\bOU\b|\(|\)/g) || []
/**
* Reconstrói a fórmula usando apenas os tokens válidos.
*/
const formulaReconstruida = tokensPermitidos.join("")
/**
* Remove espaços para comparar o texto original com o texto reconstruído.
*/
const formulaOriginalSemEspacos = formula.replace(/\s+/g, "")
const formulaReconstruidaSemEspacos = formulaReconstruida.replace(/\s+/g, "")
/**
* Se forem diferentes, há conteúdo não permitido na fórmula.
*/
if (formulaOriginalSemEspacos !== formulaReconstruidaSemEspacos) {
return false
}
/**
* Converte a fórmula para uma expressão JavaScript equivalente.
*
* NAO(x) → !x
* E → &&
* OU → ||
*/
const expressaoLogica = formula
.replace(/\{[\w:]+\}/g, "true")
.replace(/\bNAO\b/g, "!")
.replace(/\bE\b/g, "&&")
.replace(/\bOU\b/g, "||")
try {
/**
* Valida a ordem dos operadores, parênteses e estrutura lógica geral.
*/
new Function(`return (${expressaoLogica})`)()
return true
} catch {
return false
}
}
/**
* Estrutura principal do filtro delta.
*/
export const zFiltroDelta = z
.object({
/**
* Lista de condições disponíveis.
*/
condicoes: z.array(zCondicaoFiltroDelta),
/**
* Fórmula lógica que combina as condições.
*/
formula: z.string().refine(formulaFiltroDeltaValida, {
message:
"Fórmula inválida. Use apenas referências de condições {id} ou {id:sufixo}, operadores E/OU/NAO e parênteses.",
}),
})
.superRefine((value, ctx) => {
/**
* IDs das condições cadastradas.
*/
const idsCondicoes = new Set(value.condicoes.map((condicao) => condicao.id))
/**
* Referências usadas dentro da fórmula.
*/
const referenciasFormula = value.formula.match(/\{[\w:]+\}/g) || []
/**
* Verifica se toda referência da fórmula existe em condicoes.
*/
for (const referencia of referenciasFormula) {
if (!idsCondicoes.has(referencia)) {
ctx.addIssue({
code: "custom",
path: ["formula"],
message: `A referência ${referencia} não existe em condicoes.`,
})
}
}
})
export type tipoOperadorFiltroDelta = z.infer<typeof zOperadorFiltroDelta>
export type tipoColunaFiltroDelta = z.infer<typeof zColunaFiltroDelta>
export type tipoCondicaoFiltroDelta = z.infer<typeof zCondicaoFiltroDelta>
export type tipoFiltroDelta = z.infer<typeof zFiltroDelta>
export type tipoCondicaoFiltroDeltaTipado<T extends string> = tipoCondicaoFiltroDelta & {
coluna: T
}
export type tipoFiltroDeltaColunaTipada<T extends string> = {
condicoes: tipoCondicaoFiltroDeltaTipado<T>[]
formula: string
}
export const criarFiltroDelta = <T extends string>(filtro: tipoFiltroDeltaColunaTipada<T>) =>
zFiltroDelta.parse(filtro) as tipoFiltroDeltaColunaTipada<T>
/**
* Fábrica para criar filtros com colunas estritamente tipadas.
* Útil para autocompletar os nomes das colunas e garantir a estrutura no TypeScript.
*
* @example
* ```ts
* const { criarFiltroDelta } = iniciarFiltroDelta<"nome" | "idade" | "jsonb.propriedade">()
*
* const filtro = criarFiltroDelta({
* condicoes: [
* { id: "{c1}", coluna: "idade", operador: ">", valor: 18 },
* { id: "{c2}", coluna: "nome", operador: "=", valor: "luiz" },
* { id: "{c3}", coluna: "jsonb.propriedade", operador: "=", valor: "valor" },
* ],
* formula: "({c1} E {c2}) OU {c3}",
* })
* ```
*/
export const iniciarFiltroDelta = <TColunas extends string>() => {
return {
criarFiltroDelta: criarFiltroDelta<TColunas>,
}
}

View file

@ -1,14 +1,11 @@
export * from "./aleatorio" export * from "./aleatorio"
export * from "./auditoria"
export * from "./cacheMemoria" export * from "./cacheMemoria"
export * from "./constantes" export * from "./constantes"
export * from "./consulta" export * from "./consulta"
export * from "./dayjs26" export * from "./dayjs"
export * from "./ecosistema" export * from "./ecosistema"
export * from "./eLog"
export * from "./extensoes" export * from "./extensoes"
export * from "./extensoes" export * from "./extensoes"
export * from "./filtroDelta"
export * from "./local" export * from "./local"
export * from "./postgres" export * from "./postgres"
export * from "./produtos" export * from "./produtos"
@ -17,9 +14,7 @@ export * from "./testes-de-variaveis"
export * from "./texto_busca" export * from "./texto_busca"
export * from "./tipagemRotas" export * from "./tipagemRotas"
export * from "./tipagemRotas" export * from "./tipagemRotas"
export * from "./tipoFiltro.26"
export * from "./unidades_medida" export * from "./unidades_medida"
export * from "./uuid" export * from "./uuid"
export * from "./variaveisComuns" export * from "./variaveisComuns"
export * from "./zCoordenadas"
export * from "./zDocumento"
export * from "./zodCustomizados"

View file

@ -2,11 +2,18 @@
* LocalStorage Tipado * LocalStorage Tipado
* Lê ou grava um valor no localStorage, mantendo o tipo genérico <T>. * Lê ou grava um valor no localStorage, mantendo o tipo genérico <T>.
*/ */
export const localValor = <T>(chave_: string | any, valor?: T | null): T | null => { export const localValor = <T>(
const localStorage = "localStorage" in globalThis ? (globalThis as any).localStorage : undefined chave_: string | any,
valor?: T | null,
): T | null => {
const localStorage =
"localStorage" in globalThis ? (globalThis as any).localStorage : undefined
if (typeof localStorage == "undefined") return null if (typeof localStorage == "undefined") return null
const chave = typeof chave_ === "string" ? chave_ : encodeURIComponent(JSON.stringify(chave_)) const chave =
typeof chave_ === "string"
? chave_
: encodeURIComponent(JSON.stringify(chave_))
try { try {
// Grava valor se fornecido // Grava valor se fornecido

View file

@ -14,7 +14,9 @@ export const paraObjetoRegistroPg = (entrada: {
k, k,
v === undefined || v == null v === undefined || v == null
? v ? v
: typeof v == "string" || typeof v == "number" || typeof v == "boolean" : typeof v == "string" ||
typeof v == "number" ||
typeof v == "boolean"
? v ? v
: JSON.stringify(v, null, 2), : JSON.stringify(v, null, 2),
]), ]),

View file

@ -63,7 +63,9 @@ export class TipagemRotas<T extends { [q: string]: any }> {
*/ */
endereco(query: T, usarComoHash?: boolean) { endereco(query: T, usarComoHash?: boolean) {
const win = (typeof globalThis !== "undefined" && (globalThis as any).window) || undefined const win =
(typeof globalThis !== "undefined" && (globalThis as any).window) ||
undefined
const url = new URL(win ? win.location.href : "http://localhost") const url = new URL(win ? win.location.href : "http://localhost")
url.pathname = this.caminho url.pathname = this.caminho
@ -94,7 +96,9 @@ export class TipagemRotas<T extends { [q: string]: any }> {
if (this._acaoIr) { if (this._acaoIr) {
this._acaoIr(this.endereco({ ...query })) this._acaoIr(this.endereco({ ...query }))
} else { } else {
const win = (typeof globalThis !== "undefined" && (globalThis as any).window) || undefined const win =
(typeof globalThis !== "undefined" && (globalThis as any).window) ||
undefined
if (win) { if (win) {
win.location.href = this.endereco({ ...query }) win.location.href = this.endereco({ ...query })
} }
@ -120,7 +124,9 @@ export class TipagemRotas<T extends { [q: string]: any }> {
// pegar hash // pegar hash
const hash = url.hash const hash = url.hash
if (hash) { if (hash) {
const hashObj = Object.fromEntries(new URLSearchParams(hash.slice(1)).entries()) const hashObj = Object.fromEntries(
new URLSearchParams(hash.slice(1)).entries(),
)
queryObj = { ...queryObj, ...hashObj } as T queryObj = { ...queryObj, ...hashObj } as T
} }

235
src/tipoFiltro.26.ts Normal file
View 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"] } } },
],
},
],
})

View file

@ -1,130 +1,53 @@
import { NIL, v3, v4 } from "uuid"
/** /**
* Valida se uma string é um UUID válido (qualquer versão). * Valida se uma string é um UUID válido (qualquer versão).
*
* @param valor - A string que será validada.
* @returns booleano indicando se é um UUID válido.
*/ */
export const erUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i export const erUuid =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
export const validarUuid = (uuid: string | number | undefined | null) => { export const validarUuid = (uuid: string | number | undefined | null) => {
return erUuid.test(String(uuid || "")) const retorno = erUuid.test(String(uuid || ""))
} return retorno
// ── UUID v4 ──────────────────────────────────────────────────────────────────
// Usa Web Crypto API (globalThis.crypto), disponível em Node 19+, Bun e browsers.
/**
* Gera um UUID v4 (aleatório, não determinístico).
* Usa `globalThis.crypto.randomUUID()` — disponível em Node 19+, Bun e browsers modernos.
*/
export const uuidV4 = (): string => globalThis.crypto.randomUUID()
/**
* @deprecated Use uuidV4() diretamente.
*/
export const uuid = uuidV4
// ── UUID v3 (MD5 determinístico) ──────────────────────────────────────────────
// Implementação pura sem dependência de Node.js para compatibilidade front+back.
const NIL_UUID = "00000000-0000-0000-0000-000000000000"
// Rotação de 32 bits à esquerda
const rotL = (x: number, n: number) => (x << n) | (x >>> (32 - n))
// MD5 — implementação pura JS compatível com browser e Node
const md5 = (str: string): string => {
const msg = new TextEncoder().encode(str)
const len = msg.length
const bits = len * 8
// Padding
const padLen = len % 64 < 56 ? 56 - (len % 64) : 120 - (len % 64)
const padded = new Uint8Array(len + padLen + 8)
padded.set(msg)
padded[len] = 0x80
const dv = new DataView(padded.buffer)
dv.setUint32(len + padLen, bits >>> 0, true)
dv.setUint32(len + padLen + 4, Math.floor(bits / 2 ** 32), true)
// Tabela de senos
const T: number[] = Array.from(
{ length: 64 },
(_, i) => (Math.abs(Math.sin(i + 1)) * 2 ** 32) >>> 0,
)
const S = [
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4,
11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6,
10, 15, 21,
]
let a0 = 0x67452301,
b0 = 0xefcdab89,
c0 = 0x98badcfe,
d0 = 0x10325476
for (let off = 0; off < padded.length; off += 64) {
const M: number[] = []
for (let j = 0; j < 16; j++) M[j] = dv.getUint32(off + j * 4, true)
let [A, B, C, D] = [a0, b0, c0, d0]
for (let i = 0; i < 64; i++) {
let F: number, g: number
if (i < 16) {
F = (B & C) | (~B & D)
g = i
} else if (i < 32) {
F = (D & B) | (~D & C)
g = (5 * i + 1) % 16
} else if (i < 48) {
F = B ^ C ^ D
g = (3 * i + 5) % 16
} else {
F = C ^ (B | ~D)
g = (7 * i) % 16
}
F = (F + A + T[i] + M[g]) >>> 0
A = D
D = C
C = B
B = (B + rotL(F, S[i])) >>> 0
}
a0 = (a0 + A) >>> 0
b0 = (b0 + B) >>> 0
c0 = (c0 + C) >>> 0
d0 = (d0 + D) >>> 0
}
const toHexLE = (n: number) => {
let s = ""
for (let i = 0; i < 4; i++) s += ((n >>> (i * 8)) & 0xff).toString(16).padStart(2, "0")
return s
}
return toHexLE(a0) + toHexLE(b0) + toHexLE(c0) + toHexLE(d0)
}
const formatarUuidV3 = (hash: string): string => {
const c = hash.slice(0, 32)
const v = ((Number.parseInt(c[16], 16) & 0x3) | 0x8).toString(16)
return `${c.slice(0, 8)}-${c.slice(8, 12)}-3${c.slice(13, 16)}-${v}${c.slice(17, 20)}-${c.slice(20, 32)}`
} }
/** /**
* Gera um UUID determinístico (versão 3) com base em uma chave e um grupo (namespace). * Gera um UUID determinístico (versão 3) com base em uma chave e um grupo (namespace).
* Implementação pura JS (MD5), sem dependência de Node.js — funciona em browser e server.
* *
* @param chave - Valor a serializar (string, number ou objeto). * - Usa o algoritmo MD5 (RFC 4122).
* @param grupo - Namespace opcional; se omitido, usa UUID nil. * - Sempre retorna o mesmo UUID para a mesma combinação chave + grupo.
* - Caso o grupo não seja informado, usa o UUID "nil" como namespace.
*
* @param chave - Qualquer valor que será convertido em string para gerar o UUID (ex: número, string ou objeto).
* @param grupo - Opcional. Namespace para separar domínios diferentes de UUIDs.
* @returns UUID v3 (determinístico)
*/ */
export const uuidV3 = (chave: unknown, grupo?: unknown): string => { export const uuidV3 = (chave: any, grupo?: any): string => {
const namespace = grupo ? uuidV3(grupo) : NIL_UUID return v3(
const input = // Converte a chave para string (de forma segura)
typeof chave === "string" typeof chave === "string"
? chave ? chave
: typeof chave === "number" : typeof chave === "number"
? String(chave) ? String(chave)
: JSON.stringify(chave) : JSON.stringify(chave),
return formatarUuidV3(md5(namespace + input))
// Se um grupo foi fornecido, gera um UUID v3 recursivamente com base nele, senão usa NIL
grupo ? uuidV3(grupo) : NIL,
)
} }
/**
* Gera um UUID v4 (aleatório, não determinístico).
*
* - Usado quando unicidade é necessária, mas não se exige que seja previsível.
*/
export const uuidV4 = v4
/**
* @deprecated Esta variável será descontinuada em versões futuras.
* Use a função `uuidV4()` diretamente.
*/
export const uuid = uuidV4

View file

@ -1,5 +1,7 @@
export const esperar = (ms: number): Promise<true> => export const esperar = (ms: number): Promise<true> =>
new Promise((resolve: (r: true) => void) => setTimeout(() => resolve(true), ms)) new Promise((resolve: (r: true) => void) =>
setTimeout(() => resolve(true), ms),
)
/** /**
* Usado para retronat o no de uma variável, deve ser usado dentro de um objeto * Usado para retronat o no de uma variável, deve ser usado dentro de um objeto
* const nomex = {a: 1, b: 2} * const nomex = {a: 1, b: 2}
@ -7,4 +9,5 @@ export const esperar = (ms: number): Promise<true> =>
* @param v * @param v
* @returns * @returns
*/ */
export const nomeVariavel = (v: { [key: string]: any }) => Object.keys(v).join("/") export const nomeVariavel = (v: { [key: string]: any }) =>
Object.keys(v).join("/")

View file

@ -1,12 +0,0 @@
/**
* No futuro podemos melhorar este Zod para incluir mais formatos de coordenadas.
*
*/
import z from "zod"
export const zCoordenadas = z.object({
formato: z.literal("decimal").default("decimal"),
datum: z.literal("EPSG:4326").default("EPSG:4326"),
latitude: z.number(),
longitude: z.number(),
})

View file

@ -1,56 +0,0 @@
import z from "zod"
/**
Resumo – CNPJ Alfanumérico (vigência a partir de julho de 2026)
A Receita Federal passará a emitir CNPJs alfanuméricos para novas empresas a partir de julho de 2026. O objetivo é ampliar a quantidade de combinações disponíveis e evitar o esgotamento dos números atuais.
O que muda?
O CNPJ continuará com 14 caracteres.
Os 12 primeiros caracteres poderão conter letras (A-Z) e números (0-9).
Os 2 dígitos verificadores finais continuarão sendo numéricos.
Exemplo ilustrativo:
Atual: 00.000.000/0001-00
Novo: A1.B2C.3D4/EF56-78
Quem será afetado?
Empresas já existentes não terão seus CNPJs alterados.
A mudança vale apenas para novas inscrições realizadas a partir de julho de 2026.
*/
const regexCnpjNumerico = /^\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}$/
/**
Como ler o novo CNPJ (estrutura)
Tomando como exemplo um CNPJ alfanumérico fictício:
12.ABC.345/0001-67
Como ler:
12.ABC.345 é a raiz (identificação da empresa)
0001 é o sufixo (estabelecimento, geralmente “0001” para matriz)
67 são os dígitos verificadores numéricos
Pontos de atenção:
Letras maiúsculas (não há diferenciação entre maiúscula e minúscula no sistema, mas convenção é maiúscula)
Não usar caracteres especiais: só letras de A a Z e números de 0 a 9
Pontos, barra e hífen mantidos como antes
*/
const regexCnpjAlfanumerico = /^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}\/[A-Z0-9]{4}-\d{2}$/i
const yyyymm = Number(new Date().toISOString().slice(0, 7).replace("-", ""))
export const zDocCnpj = z
.string()
.regex(yyyymm < 202407 ? regexCnpjNumerico : regexCnpjAlfanumerico)
.describe("Documento (CNPJ) no formato XX.XXX.XXX/XXXX-XX")
export const zDocCpf = z
.string()
.regex(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/)
.describe("Documento (CPF) no formato XXX.XXX.XXX-XX")
export const zDocumento = zDocCpf.or(zDocCnpj).describe("CPF ou CNPJ")

View file

@ -1,39 +0,0 @@
import z from "zod"
const zPreprocessarNumero = (p: unknown) => {
if (typeof p === "number") return p
if (typeof p !== "string") return p
let p2 = p
if (p2.includes(",")) {
// ponto de milhar → remove; vírgula decimal → troca por ponto
p2 = p2.replace(/\./g, "").replace(",", ".")
}
// remove tudo que não seja dígito ou ponto decimal
p2 = p2.replace(/[^0-9.]/g, "")
if (p2 == "") return null
return Number(p2)
}
/**
* Schema numérico que aceita strings legadas e normaliza para `number`.
*
* O campo **é** um número. O `preprocess` resolve compatibilidade com dados
* antigos onde o frontend enviava strings formatadas (BR ou monetária).
*
* Formatos de entrada aceitos:
* - `10` → number direto
* - `10.1` → ponto decimal
* - `10,1` → vírgula decimal (BR)
* - `1.000,1` → milhar com ponto + vírgula decimal (BR)
* - `R$ 10,01` → prefixo monetário legado
*/
export const zNumero = z.preprocess(zPreprocessarNumero, z.number())
export const zNumeroPositivo = z.preprocess(zPreprocessarNumero, z.number().positive())
export const zNumeroInteiro = z.preprocess(zPreprocessarNumero, z.number().int())

View file

@ -6,15 +6,13 @@
/* Linguagem e Ambiente */ /* Linguagem e Ambiente */
"target": "ES2020" /* Define a versão do JavaScript para o código emitido. */, "target": "ES2020" /* Define a versão do JavaScript para o código emitido. */,
"lib": [ "lib": [
"ES2020", "dom.iterable"
"DOM",
"DOM.Iterable"
] /* Especifica as bibliotecas padrão a serem incluídas, como DOM para iteradores. */, ] /* Especifica as bibliotecas padrão a serem incluídas, como DOM para iteradores. */,
"experimentalDecorators": true /* Habilita o suporte experimental a decoradores. */, "experimentalDecorators": true /* Habilita o suporte experimental a decoradores. */,
"emitDecoratorMetadata": true /* Emite metadados de tipos de design para declarações decoradas. */, "emitDecoratorMetadata": true /* Emite metadados de tipos de design para declarações decoradas. */,
/* Módulos */ /* Módulos */
"moduleResolution": "bundler" /* Define como o TypeScript resolve módulos. */, "moduleResolution": "node" /* Define como o TypeScript resolve módulos. */,
"rootDir": "./src" /* Define a pasta raiz para os arquivos de origem. */, "rootDir": "./src" /* Define a pasta raiz para os arquivos de origem. */,
/* Emissão */ /* Emissão */
@ -25,9 +23,7 @@
/* Verificação de Tipos */ /* Verificação de Tipos */
"strict": true /* Habilita todas as opções de verificação estrita de tipos. */, "strict": true /* Habilita todas as opções de verificação estrita de tipos. */,
"skipLibCheck": true /* Ignora a verificação de tipos em arquivos de declaração de bibliotecas. */, "skipLibCheck": true /* Ignora a verificação de tipos em arquivos de declaração de bibliotecas. */
// IA manter "ignoreDeprecations": "6.0",
"ignoreDeprecations": "6.0"
}, },
"include": [ "include": [
"src/**/*" "src/**/*"

View file

@ -18,12 +18,7 @@ export const tsup_config_back: Options = {
minify: false, // Geralmente não minificamos o código do backend em produção, mas você pode mudar minify: false, // Geralmente não minificamos o código do backend em produção, mas você pode mudar
platform: "node", platform: "node",
outExtension: () => ({ js: ".js" }), outExtension: () => ({ js: ".js" }),
loader: {
".svg": "text",
".md": "text",
},
} }
// Exporta a configuração padrão usando defineConfig // Exporta a configuração padrão usando defineConfig
export default defineConfig(tsup_config_back) export default defineConfig(tsup_config_back)

View file

@ -19,10 +19,6 @@ export const tsup_config_front: Options = {
external: ['dayjs', 'cross-fetch', 'uuid', 'zod'], external: ['dayjs', 'cross-fetch', 'uuid', 'zod'],
outExtension: () => ({ js: ".mjs" }), outExtension: () => ({ js: ".mjs" }),
shims: false, shims: false,
loader: {
".svg": "text",
".md": "text",
},
} }
// Exporta a configuração padrão usando defineConfig // Exporta a configuração padrão usando defineConfig