Merge branch 'producao'

This commit is contained in:
Luiz Silva 2025-07-04 22:30:02 -03:00
commit aa7953e452
53 changed files with 1209 additions and 335 deletions

View file

@ -1,26 +0,0 @@
import { z } from "zod"
export const InterfaceAuntenticacao = z.object({
// usuários
codigo_usuario: z.string().uuid(),
nome_usuario: z.string(),
email_usuario: z.string(),
documento_usuario: z.string(),
organizacao: z.string(),
rotas: z.object({}),
// Dados do sistema
sistema: z.string(),
sistema_cor: z.string(),
sistema_nome: z.string(),
sistema_logo: z.string(),
// integrações
/** as url de integração serão armazenadas pelo sistema resíduos e identificado pelo código do token */
codigo_token: z.string(),
url_usuarios: z.string().url(),
url_empreendedores: z.string().url(),
url_empreendimentos: z.string().url(),
})

View file

@ -1,3 +0,0 @@
/** Sistemas vão conversar por meio de autorizações tipar eles aqui */
export * from "./auntenticacaoResiduos"

View file

@ -8,9 +8,15 @@ export enum camposComuns {
data_hora_atualizacao = "data_hora_atualizacao",
codigo_usuario_criacao = "codigo_usuario_criacao",
codigo_usuario_atualizacao = "codigo_usuario_atualizacao",
versao = "versao",
}
/** Palavras comumente usadas */
export enum tx {
token = "token",
}
export enum tipoUsuarioResiduos {
Usuario = "usuario",
Fornecedor = "fornecedor",
}

177
src/extensoes.ts Normal file
View file

@ -0,0 +1,177 @@
type tiposArquivo = "imagem" | "documento" | "vídeo" | "outros"
export const extensoes: {
ext: string
tipo: tiposArquivo
mime: string
}[] = [
{
ext: "gif",
tipo: "imagem",
mime: "image/gif",
},
{
ext: "jpg",
tipo: "imagem",
mime: "image/jpeg",
},
{
ext: "jpeg",
tipo: "imagem",
mime: "image/jpeg",
},
{
ext: "png",
tipo: "imagem",
mime: "image/png",
},
{
ext: "bmp",
tipo: "imagem",
mime: "image/bmp",
},
{
ext: "webp",
tipo: "imagem",
mime: "image/webp",
},
{
ext: "tiff",
tipo: "imagem",
mime: "image/tiff",
},
{
ext: "svg",
tipo: "imagem",
mime: "image/svg+xml",
},
{
ext: "ico",
tipo: "imagem",
mime: "image/x-icon",
},
{
ext: "pdf",
tipo: "documento",
mime: "application/pdf",
},
{
ext: "doc",
tipo: "documento",
mime: "application/msword",
},
{
ext: "docx",
tipo: "documento",
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
},
{
ext: "xls",
tipo: "documento",
mime: "application/vnd.ms-excel",
},
{
ext: "xlsx",
tipo: "documento",
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
},
{
ext: "ppt",
tipo: "documento",
mime: "application/vnd.ms-powerpoint",
},
{
ext: "pptx",
tipo: "documento",
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
},
{
ext: "txt",
tipo: "documento",
mime: "text/plain",
},
{
ext: "odt",
tipo: "documento",
mime: "application/vnd.oasis.opendocument.text",
},
{
ext: "ods",
tipo: "documento",
mime: "application/vnd.oasis.opendocument.spreadsheet",
},
{
ext: "rtf",
tipo: "documento",
mime: "application/rtf",
},
{
ext: "csv",
tipo: "documento",
mime: "text/csv",
},
{
ext: "mp4",
tipo: "vídeo",
mime: "video/mp4",
},
{
ext: "avi",
tipo: "vídeo",
mime: "video/x-msvideo",
},
{
ext: "mkv",
tipo: "vídeo",
mime: "video/x-matroska",
},
{
ext: "mov",
tipo: "vídeo",
mime: "video/quicktime",
},
{
ext: "wmv",
tipo: "vídeo",
mime: "video/x-ms-wmv",
},
{
ext: "flv",
tipo: "vídeo",
mime: "video/x-flv",
},
{
ext: "webm",
tipo: "vídeo",
mime: "video/webm",
},
{
ext: "3gp",
tipo: "vídeo",
mime: "video/3gpp",
},
{
ext: "mpeg",
tipo: "vídeo",
mime: "video/mpeg",
},
]
/**
* Função que retorna o tipo do arquivo
* @param nomeArquivo
* @returns
*/
export const tipoArquivo = (
nomeArquivo: string | null | undefined,
): tiposArquivo => {
// extenssão do arquivo
const extArquivo = String(nomeArquivo || "")
.toLocaleLowerCase()
.split(".")
.pop()
// procura a extensão do arquivo na lista de extensões
const extensao = extensoes.find((extensao) => extensao.ext === extArquivo)
// retorna o tipo do arquivo
return extensao?.tipo || "outros"
}

View file

@ -1,9 +1,11 @@
export * from "./autorizacoes"
export * from "./aleatorio"
export * from "./constantes"
export * from "./consulta"
export * from "./aleatorio"
export * from "./ecosistema"
export * from "./extensoes"
export * from "./logger"
export * from "./texto_busca"
export * from "./tipagemRotas"
export * from "./unidades_medida"
export * from "./uuid"
export * from "./provedores"
export * from "./ecosistema"
export * from "./variaveisComuns"

126
src/logger.ts Normal file
View file

@ -0,0 +1,126 @@
import crossFetch from "cross-fetch"
import { nomeVariavel } from "./variaveisComuns"
const LOKI_BASE_URL = "https://log.idz.one"
const LOKI_ENDPOINT = "/loki/api/v1/push"
export type tipoLokiObjeto = {
streams: {
stream: {
[k: string]: string
}
values: [string, string][]
}[]
}
export const postLogger = async ({
objeto,
}: {
objeto: tipoLokiObjeto
}): Promise<[objeto: tipoLokiObjeto, erro?: string]> => {
const response = await crossFetch(`${LOKI_BASE_URL}${LOKI_ENDPOINT}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(objeto),
}).catch((a) => a)
if (!response.ok) {
return [objeto, `Erro ${response.status}: ${await response?.text?.()}`]
}
return [objeto]
}
let cwd = ""
/** define a localização da pasta do projeto */
export const defineCwd = (novoCwd: string) => {
cwd = novoCwd
}
type tipoLevel = "info" | "warn" | "error"
type tipoOpSessao = {
inquilino: string
usuario: string
parametros?: { [k: string]: string }
}
type tipoLog = {
detalhes?: unknown[]
__filename?: string
local?: string
parametros?: { [k: string]: string }
}
export type tipoLoggerLog = (
level: tipoLevel,
mensagem: string,
op_tipoLog?: tipoLog,
) => Promise<[objeto: tipoLokiObjeto, erro?: string]>
export type TipoLoggerSessao = (sess: tipoOpSessao) => tipoLoggerLog
export type tipoLogger = (amb: {
app: string
eProducao: boolean
parametros?: {
[k: string]: string
}
}) => TipoLoggerSessao
export const logger: tipoLogger =
({ app: app_e, eProducao, parametros: parametrosAmbiente }) =>
({ inquilino, usuario, parametros: parametrosSessao }) =>
async (level, mensagem, op_tipoLog) => {
let {
__filename,
detalhes,
local,
parametros: parametrosLog,
} = op_tipoLog || {}
const app = `${eProducao ? "" : "DEV-"}${app_e}`
if (cwd && __filename) {
__filename = __filename.replace(cwd, "")
}
if (local) {
detalhes = [`${nomeVariavel({ local })}="${local}"`, ...(detalhes || [])]
}
if (__filename) {
detalhes = [
`${nomeVariavel({ __filename })}="${__filename}"`,
...(detalhes || []),
]
}
const timestamp = `${Date.now()}000000`
const mainLog = detalhes?.length
? `${mensagem} | ${detalhes.map((d) => JSON.stringify(d)).join(" | ")}`
: mensagem
const payload: tipoLokiObjeto["streams"][number] = {
stream: {
app,
inquilino,
usuario,
level,
...(parametrosAmbiente || {}),
...(parametrosSessao || {}),
...(parametrosLog || {}),
},
values: [
[
timestamp,
mainLog, // Linha de log direta
],
],
}
const objeto: tipoLokiObjeto = { streams: [payload] }
const response = await postLogger({ objeto })
return response
}

View file

@ -1,4 +0,0 @@
export enum provedores {
"betha-sistemas" = "Betha Sistemas",
"e-licencie" = "e-licencie",
}

13
src/teste.ts Normal file
View file

@ -0,0 +1,13 @@
import { logger } from "./logger"
const l = logger({ app: "teste", eProducao: true })
const lg = l({
inquilino: "conta_1",
usuario: "pedrinho",
})
lg("error", "Deu Ruim").then((a) => console.log(JSON.stringify(a)))
lg("info", "Deu Bom", { __filename }).then((a) =>
console.log(JSON.stringify(a)),
)

View file

@ -7,7 +7,6 @@ export const texto_busca = (...texto: any[]): string =>
? ""
: String(txt)
.normalize("NFD")
// biome-ignore lint/suspicious/noMisleadingCharacterClass: <explanation>
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, " ")
.toLowerCase(),

120
src/tipagemRotas.ts Normal file
View file

@ -0,0 +1,120 @@
/** Gerar uma classe que facilita a gestão de rotas com a tipagem das querys
*
* Definições:
*
* caminho = "/aplicacao/funcionalidade"
*
* endereco = "http://localhost:3000/aplicacao/funcionalidade"
*
* parametros = {nome:"José"}
*/
export class TipagemRotas<T extends { [q: string]: string | undefined }> {
_partesCaminho: string[] = []
_acaoIr?: (endereco: string) => undefined
/** Ao criar novo obijeto de tipagem de rota é necessário passar o caminho parcial
** export const mCaminho = new TipagemRotas<{q:string}>("aplicacao","funcionalidade")
*/
constructor({
caminho,
acaoIr,
}: {
caminho: string[] | string
acaoIr?: undefined | ((endereco: string) => undefined)
}) {
this._acaoIr = acaoIr
this._partesCaminho = (Array.isArray(caminho) ? caminho : [caminho])
.flatMap((a) => a.split("/"))
.filter(Boolean)
}
/** Retorna o caminho completo da rota
** console.log(mCaminho.caminho)
** "/caminho"
*/
get caminho() {
const ret = `/${this._partesCaminho.join("/")}`
return ret
}
/** Define o caminho completo da rota
** mCaminho.caminho = "/novoCaminho"
** console.log(mCaminho.caminho)
** "/novoCaminho"
** */
set caminho(caminhoParcial: string) {
this._partesCaminho = caminhoParcial.split("/").filter((parte) => parte)
}
/** Retorna o caminho completo da rota com a query
** console.log(mCaminho.resolve({q:"query"}))
** "http://localhost:3000/caminho?q=query"
*/
endereco(query: T, usarComoHash?: boolean) {
const url = new URL(
typeof window !== "undefined" ? window.location.href : "http://localhost",
)
url.pathname = this.caminho
url.search = ""
const queryKeys = Object.entries(query)
for (const [key, value] of queryKeys) {
url.searchParams.set(
String(key),
value === undefined || value === null ? "" : value,
)
}
url.hash = ""
if (usarComoHash) {
url.hash = `#${url.search}`
url.search = ""
}
return url.href
}
/** Vai para a url
** mCaminho.ir({q:"query"})
** window.location.href = "http://localhost:3000/caminho?q=query"
*/
ir(query: T) {
if (this._acaoIr) {
this._acaoIr(this.endereco(query))
} else {
if (typeof window != "undefined") {
window.location.href = this.endereco(query)
}
}
}
/** Retorna os parametros da url
** console.log(mCaminho.parametros())
** {q:"query"}
*/
get parametros() {
const url = new URL(
typeof window !== "undefined" ? window.location.href : "http://localhost",
)
const query = url.searchParams
const queryObj = Object.fromEntries(query.entries())
// pegar hash
const hash = url.hash
if (hash) {
const hashObj = Object.fromEntries(
new URLSearchParams(hash.slice(1)).entries(),
)
return { ...queryObj, ...hashObj } as T
}
return queryObj as Partial<T>
}
}

View file

@ -1,79 +1,71 @@
/**
* Essa variável se conecta a tabela_lidades
*
* onde sigla se conecta com sigla
*
* Usuário terá mais opções de unidades, quando fazer o envio para o mtr, usar a opção fornecida pelo usuarios, caso não tenha
* usar a normalizada
*/
export enum siglas_unidades_medida {
UN = "UN",
KG = "KG",
TON = "TON",
g = "g",
"M³" = "M³",
Lt = "Lt",
}
export const unidades_medida: {
unidade: string
sigla_unidade: keyof typeof siglas_unidades_medida
nome: string
unidade_normalizada: string
sigla_normalizada: keyof typeof siglas_unidades_medida
normalizar: (valor: number) => number
tipo: "massa" | "volume" | "comprimento"
tipo: "massa" | "volume" | "comprimento" | "unidade"
}[] = [
{
unidade: "kg",
sigla_unidade: "KG",
nome: "Quilograma",
unidade_normalizada: "kg",
sigla_normalizada: "KG",
normalizar: (valor: number) => valor,
tipo: "massa",
},
{
unidade: "g",
sigla_unidade: "g",
nome: "Grama",
unidade_normalizada: "kg",
sigla_normalizada: "KG",
normalizar: (valor: number) => valor / 1000,
tipo: "massa",
},
{
unidade: "ton",
sigla_unidade: "TON",
nome: "Tonelada",
unidade_normalizada: "kg",
sigla_normalizada: "KG",
normalizar: (valor: number) => valor * 1000,
tipo: "massa",
},
{
unidade: "L",
sigla_unidade: "Lt",
nome: "Litro",
unidade_normalizada: "L",
sigla_normalizada: "Lt",
normalizar: (valor: number) => valor,
tipo: "volume",
},
{
unidade: "m3",
sigla_unidade: "M³",
nome: "Metro Cúbico",
unidade_normalizada: "L",
sigla_normalizada: "Lt",
normalizar: (valor: number) => valor * 1000,
tipo: "volume",
},
{
unidade: "mL",
nome: "Mililitro",
unidade_normalizada: "L",
normalizar: (valor: number) => valor / 1000,
tipo: "volume",
},
{
unidade: "cm",
nome: "Centímetro",
unidade_normalizada: "m",
normalizar: (valor: number) => valor / 100,
tipo: "comprimento",
},
{
unidade: "mm",
nome: "Milímetro",
unidade_normalizada: "m",
normalizar: (valor: number) => valor / 1000,
tipo: "comprimento",
},
{
unidade: "m",
nome: "Metro",
unidade_normalizada: "m",
sigla_unidade: "UN",
nome: "Unidade",
sigla_normalizada: "UN",
normalizar: (valor: number) => valor,
tipo: "comprimento",
},
{
unidade: "km",
nome: "Quilômetro",
unidade_normalizada: "m",
normalizar: (valor: number) => valor * 1000,
tipo: "comprimento",
tipo: "unidade",
},
{
unidade: "UN",

View file

@ -2,3 +2,12 @@ export const esperar = (ms: number): Promise<true> =>
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
* const nomex = {a: 1, b: 2}
* nomeVariavel({nomex}) // retorna "nomex"
* @param v
* @returns
*/
export const nomeVariavel = (v: { [key: string]: any }) =>
Object.keys(v).join("/")