feat: uuid sem node:crypto (Web Crypto API + MD5 puro), DTS restaurado, bump v0.355.0
This commit is contained in:
parent
fdfe409088
commit
7f9f022b9c
5 changed files with 921 additions and 63 deletions
|
|
@ -25,33 +25,143 @@ __export(uuid_exports, {
|
||||||
validarUuid: () => validarUuid
|
validarUuid: () => validarUuid
|
||||||
});
|
});
|
||||||
module.exports = __toCommonJS(uuid_exports);
|
module.exports = __toCommonJS(uuid_exports);
|
||||||
var import_node_crypto = require("node:crypto");
|
|
||||||
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) => {
|
||||||
const retorno = erUuid.test(String(uuid2 || ""));
|
return erUuid.test(String(uuid2 || ""));
|
||||||
return retorno;
|
|
||||||
};
|
};
|
||||||
|
const uuidV4 = () => globalThis.crypto.randomUUID();
|
||||||
|
const uuid = uuidV4;
|
||||||
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
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 formatarUuidV3 = (hash) => {
|
||||||
const chars = hash.slice(0, 32);
|
const c = hash.slice(0, 32);
|
||||||
return [
|
const v = (Number.parseInt(c[16], 16) & 3 | 8).toString(16);
|
||||||
chars.slice(0, 8),
|
return `${c.slice(0, 8)}-${c.slice(8, 12)}-3${c.slice(13, 16)}-${v}${c.slice(17, 20)}-${c.slice(20, 32)}`;
|
||||||
chars.slice(8, 12),
|
|
||||||
`3${chars.slice(13, 16)}`,
|
|
||||||
// version 3
|
|
||||||
`${(Number.parseInt(chars[16], 16) & 3 | 8).toString(16)}${chars.slice(17, 20)}`,
|
|
||||||
// variant
|
|
||||||
chars.slice(20, 32)
|
|
||||||
].join("-");
|
|
||||||
};
|
};
|
||||||
const uuidV3 = (chave, grupo) => {
|
const uuidV3 = (chave, grupo) => {
|
||||||
const namespace = grupo ? uuidV3(grupo) : NIL_UUID;
|
const namespace = grupo ? uuidV3(grupo) : NIL_UUID;
|
||||||
const input = typeof chave === "string" ? chave : typeof chave === "number" ? String(chave) : JSON.stringify(chave);
|
const input = typeof chave === "string" ? chave : typeof chave === "number" ? String(chave) : JSON.stringify(chave);
|
||||||
const hash = (0, import_node_crypto.createHash)("md5").update(namespace + input).digest("hex");
|
return formatarUuidV3(md5(namespace + input));
|
||||||
return formatarUuidV3(hash);
|
|
||||||
};
|
};
|
||||||
const uuidV4 = () => (0, import_node_crypto.randomUUID)();
|
|
||||||
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,
|
||||||
|
|
|
||||||
688
dist-front/index.d.mts
Normal file
688
dist-front/index.d.mts
Normal file
|
|
@ -0,0 +1,688 @@
|
||||||
|
import z from 'zod';
|
||||||
|
import _dayjs from 'dayjs';
|
||||||
|
export { Dayjs, ManipulateType } 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';
|
||||||
|
|
||||||
|
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 */
|
||||||
|
declare const cacheM: <T>(chave: any, valor?: T, validadeSeg?: number) => T | undefined;
|
||||||
|
declare const verCacheM: () => {
|
||||||
|
[k: string]: {
|
||||||
|
/** new Date().getTime() */
|
||||||
|
validade?: number | undefined;
|
||||||
|
valor: any;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
declare const cacheMemoria: <T>(chave: any, valor?: T, validadeSeg?: number) => T | undefined;
|
||||||
|
/** para uso fixo dentro de uma função, trava a chave */
|
||||||
|
declare const cacheMFixo: (chave: any) => <T>(valor?: T) => T | undefined;
|
||||||
|
|
||||||
|
declare const uuid_null = "00000000-0000-0000-0000-000000000000";
|
||||||
|
/** Colunas Presentes n maioria das tabelas */
|
||||||
|
declare enum camposComuns {
|
||||||
|
codigo = "codigo",
|
||||||
|
excluido = "excluido",
|
||||||
|
data_hora_criacao = "data_hora_criacao",
|
||||||
|
data_hora_atualizacao = "data_hora_atualizacao",
|
||||||
|
codigo_usuario_criacao = "codigo_usuario_criacao",
|
||||||
|
codigo_usuario_atualizacao = "codigo_usuario_atualizacao",
|
||||||
|
versao = "versao"
|
||||||
|
}
|
||||||
|
/** Palavras comumente usadas */
|
||||||
|
declare enum tx {
|
||||||
|
token = "token"
|
||||||
|
}
|
||||||
|
declare enum tipoUsuarioResiduos {
|
||||||
|
Usuario = "usuario",
|
||||||
|
Fornecedor = "fornecedor"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare enum operadores {
|
||||||
|
"=" = "=",
|
||||||
|
"!=" = "!=",
|
||||||
|
">" = ">",
|
||||||
|
">=" = ">=",
|
||||||
|
"<" = "<",
|
||||||
|
"<=" = "<=",
|
||||||
|
like = "like",
|
||||||
|
in = "in",
|
||||||
|
isNull = "isNull",
|
||||||
|
notIn = "notIn"
|
||||||
|
}
|
||||||
|
type tipoFiltro = {
|
||||||
|
coluna: string;
|
||||||
|
valor: any;
|
||||||
|
operador: keyof typeof operadores | operadores;
|
||||||
|
ou?: boolean;
|
||||||
|
};
|
||||||
|
type interfaceConsulta = {
|
||||||
|
offset?: number;
|
||||||
|
limit?: number;
|
||||||
|
filtros?: tipoFiltro[];
|
||||||
|
ordem?: string;
|
||||||
|
ordemTipo?: "asc" | "desc";
|
||||||
|
colunas?: string[];
|
||||||
|
apenasConsulta?: boolean;
|
||||||
|
apenasContagem?: boolean;
|
||||||
|
};
|
||||||
|
declare const zOperadores: z.ZodEnum<{
|
||||||
|
"=": "=";
|
||||||
|
"!=": "!=";
|
||||||
|
">": ">";
|
||||||
|
">=": ">=";
|
||||||
|
"<": "<";
|
||||||
|
"<=": "<=";
|
||||||
|
like: "like";
|
||||||
|
in: "in";
|
||||||
|
isNull: "isNull";
|
||||||
|
notIn: "notIn";
|
||||||
|
}>;
|
||||||
|
declare const zFiltro: z.ZodObject<{
|
||||||
|
coluna: z.ZodString;
|
||||||
|
valor: z.ZodAny;
|
||||||
|
operador: z.ZodEnum<{
|
||||||
|
"=": "=";
|
||||||
|
"!=": "!=";
|
||||||
|
">": ">";
|
||||||
|
">=": ">=";
|
||||||
|
"<": "<";
|
||||||
|
"<=": "<=";
|
||||||
|
like: "like";
|
||||||
|
in: "in";
|
||||||
|
isNull: "isNull";
|
||||||
|
notIn: "notIn";
|
||||||
|
}>;
|
||||||
|
ou: z.ZodOptional<z.ZodBoolean>;
|
||||||
|
}, z.core.$strip>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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";
|
||||||
|
|
||||||
|
/** 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";
|
||||||
|
declare const extensoes: {
|
||||||
|
ext: string;
|
||||||
|
tipo: tiposArquivo;
|
||||||
|
mime: string;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* Função que retorna o tipo do arquivo
|
||||||
|
* @param nomeArquivo
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* Lê ou grava um valor no localStorage, mantendo o tipo genérico <T>.
|
||||||
|
*/
|
||||||
|
declare const localValor: <T>(chave_: string | any, valor?: T | null) => T | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trata um objeto para ser imput para postgres
|
||||||
|
* @param entrada
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
declare const paraObjetoRegistroPg: (entrada: {
|
||||||
|
[k: string]: any;
|
||||||
|
}) => {
|
||||||
|
[k: string]: string | boolean | null | undefined | number;
|
||||||
|
};
|
||||||
|
declare const pgObjeto: (entrada: {
|
||||||
|
[k: string]: any;
|
||||||
|
}) => {
|
||||||
|
[k: string]: string | boolean | null | undefined | number;
|
||||||
|
};
|
||||||
|
declare const objetoPg: (entrada: {
|
||||||
|
[k: string]: any;
|
||||||
|
}) => {
|
||||||
|
[k: string]: string | boolean | null | undefined | number;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare enum Produtos {
|
||||||
|
"e-licencie" = "e-licencie",
|
||||||
|
"gov.e-licencie" = "gov.e-licencie"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare enum tiposSituacoesElicencie {
|
||||||
|
modelo = "000_modelo",
|
||||||
|
vencida = "100_vencida",
|
||||||
|
expirado = "200_expirado",
|
||||||
|
alerta = "300_alerta",
|
||||||
|
protocoladafora = "350_protocoladafora",
|
||||||
|
protocolada = "400_protocolada",
|
||||||
|
protocoladaApenas = "430_protocolada",
|
||||||
|
protocolada_alteracao = "450_protocolada",
|
||||||
|
prazo = "500_prazo",
|
||||||
|
emitida = "515_emitida",
|
||||||
|
valida = "518_valida",
|
||||||
|
novo = "520_novo",
|
||||||
|
recebido = "521_recebido",
|
||||||
|
em_andamento = "530_em_andamento",
|
||||||
|
aguardando = "530_aguardando",
|
||||||
|
aguardandoresposta = "540_aguardandoresposta",
|
||||||
|
suspensaotemporaria = "540_suspensaotemporaria",
|
||||||
|
cancelada = "550_cancelada",
|
||||||
|
execucao = "560_execucao",
|
||||||
|
pendente = "570_pendente",
|
||||||
|
executadafora = "600_executadafora",
|
||||||
|
executada = "700_executada",
|
||||||
|
naoexecutada = "701_naoexecutada",
|
||||||
|
concluida = "730_concluida",
|
||||||
|
respondido_negado = "740_respondido_negado",
|
||||||
|
respondido_aceito = "741_respondido_aceito",
|
||||||
|
atendidoparcial = "742_atendidoparcial",
|
||||||
|
naoatendido = "743_naoatendido",
|
||||||
|
atendido = "744_atendido",
|
||||||
|
renovada = "760_renovada",
|
||||||
|
finalizada = "800_finalizada",
|
||||||
|
emitirnota = "101_emitirnota",
|
||||||
|
faturaatrasada = "301_faturaatrasada",
|
||||||
|
pagarfatura = "302_pagarfatura",
|
||||||
|
aguardandoconfirmacao = "531_aguardandoconfirmacao",
|
||||||
|
agendado = "701_agendado",
|
||||||
|
faturapaga = "801_faturapaga",
|
||||||
|
excluida = "999_excluida",
|
||||||
|
requerida = "401_requerida",
|
||||||
|
vigente = "516_vigente",
|
||||||
|
emrenovacao = "402_emrenovacao",
|
||||||
|
arquivada = "801_arquivada",
|
||||||
|
aguardando_sincronizacao = "999_aguardando_sincronizacao",
|
||||||
|
nao_conforme = "710_nao_conforme",
|
||||||
|
conforme = "720_conforme",
|
||||||
|
nao_aplicavel = "730_nao_aplicavel",
|
||||||
|
parcial = "715_parcial"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const umaFuncao: () => string;
|
||||||
|
|
||||||
|
declare const umaVariavel = "Ol\u00E1 Mundo! (vari\u00E1vel)";
|
||||||
|
|
||||||
|
/** gerar o texto de busca removendo caracteres especies e caixa alta */
|
||||||
|
declare const texto_busca: (...texto: any[]) => string;
|
||||||
|
|
||||||
|
/** 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é"}
|
||||||
|
*/
|
||||||
|
declare class TipagemRotas<T extends {
|
||||||
|
[q: string]: any;
|
||||||
|
}> {
|
||||||
|
_partesCaminho: string[];
|
||||||
|
_acaoIr?: (endereco: string) => undefined;
|
||||||
|
rotulo: 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, rotulo, }: {
|
||||||
|
caminho: (string | null | undefined)[] | string;
|
||||||
|
acaoIr?: undefined | ((endereco: string) => undefined);
|
||||||
|
/** Rotulo da página
|
||||||
|
* Inicio | Controle
|
||||||
|
*/
|
||||||
|
rotulo?: string;
|
||||||
|
});
|
||||||
|
/** Retorna o caminho completo da rota
|
||||||
|
** console.log(mCaminho.caminho)
|
||||||
|
** "/caminho"
|
||||||
|
*/
|
||||||
|
get caminho(): string;
|
||||||
|
/** Define o caminho completo da rota
|
||||||
|
** mCaminho.caminho = "/novoCaminho"
|
||||||
|
** console.log(mCaminho.caminho)
|
||||||
|
** "/novoCaminho"
|
||||||
|
** */
|
||||||
|
set caminho(caminhoParcial: string);
|
||||||
|
/** 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): string;
|
||||||
|
/** Vai para a url
|
||||||
|
** mCaminho.ir({q:"query"})
|
||||||
|
** window.location.href = "http://localhost:3000/caminho?q=query"
|
||||||
|
*/
|
||||||
|
ir(query: T): void;
|
||||||
|
/** Retorna os parametros da url
|
||||||
|
** console.log(mCaminho.parametros())
|
||||||
|
** {q:"query"}
|
||||||
|
*/
|
||||||
|
parametros(urlEntrada?: string): Partial<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
declare enum siglas_unidades_medida {
|
||||||
|
UN = "UN",
|
||||||
|
KG = "KG",
|
||||||
|
TON = "TON",
|
||||||
|
g = "g",
|
||||||
|
"M³" = "M\u00B3",
|
||||||
|
Lt = "Lt"
|
||||||
|
}
|
||||||
|
declare const unidades_medida: {
|
||||||
|
sigla_unidade: keyof typeof siglas_unidades_medida;
|
||||||
|
nome: string;
|
||||||
|
sigla_normalizada: keyof typeof siglas_unidades_medida;
|
||||||
|
normalizar: (valor: number) => number;
|
||||||
|
tipo: "massa" | "volume" | "comprimento" | "unidade";
|
||||||
|
}[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valida se uma string é um UUID válido (qualquer versão).
|
||||||
|
*/
|
||||||
|
declare const erUuid: RegExp;
|
||||||
|
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).
|
||||||
|
* 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).
|
||||||
|
* @param grupo - Namespace opcional; se omitido, usa UUID nil.
|
||||||
|
*/
|
||||||
|
declare const uuidV3: (chave: unknown, grupo?: unknown) => string;
|
||||||
|
|
||||||
|
declare const esperar: (ms: number) => Promise<true>;
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
declare const nomeVariavel: (v: {
|
||||||
|
[key: string]: any;
|
||||||
|
}) => string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "p-comuns",
|
"name": "p-comuns",
|
||||||
"version": "0.354.0",
|
"version": "0.355.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./dist-front/index.mjs",
|
"main": "./dist-front/index.mjs",
|
||||||
"module": "./dist-front/index.mjs",
|
"module": "./dist-front/index.mjs",
|
||||||
|
|
|
||||||
148
src/uuid.ts
148
src/uuid.ts
|
|
@ -1,45 +1,122 @@
|
||||||
import { createHash, randomUUID } from "node:crypto"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) => {
|
||||||
const retorno = erUuid.test(String(uuid || ""))
|
return 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"
|
const NIL_UUID = "00000000-0000-0000-0000-000000000000"
|
||||||
|
|
||||||
/**
|
// Rotação de 32 bits à esquerda
|
||||||
* Formata um hash MD5 (32 hex chars) no formato UUID v3.
|
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 formatarUuidV3 = (hash: string): string => {
|
||||||
// UUID v3: versão = 3, variante = 0b10xx (RFC 4122)
|
const c = hash.slice(0, 32)
|
||||||
const chars = hash.slice(0, 32)
|
const v = ((Number.parseInt(c[16], 16) & 0x3) | 0x8).toString(16)
|
||||||
return [
|
return `${c.slice(0, 8)}-${c.slice(8, 12)}-3${c.slice(13, 16)}-${v}${c.slice(17, 20)}-${c.slice(20, 32)}`
|
||||||
chars.slice(0, 8),
|
|
||||||
chars.slice(8, 12),
|
|
||||||
`3${chars.slice(13, 16)}`, // version 3
|
|
||||||
`${((Number.parseInt(chars[16], 16) & 0x3) | 0x8).toString(16)}${chars.slice(17, 20)}`, // variant
|
|
||||||
chars.slice(20, 32),
|
|
||||||
].join("-")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
* - Usa o algoritmo MD5 (RFC 4122).
|
* @param chave - Valor a serializar (string, number ou objeto).
|
||||||
* - Sempre retorna o mesmo UUID para a mesma combinação chave + grupo.
|
* @param grupo - Namespace opcional; se omitido, usa UUID nil.
|
||||||
* - 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: unknown, grupo?: unknown): string => {
|
||||||
const namespace = grupo ? uuidV3(grupo) : NIL_UUID
|
const namespace = grupo ? uuidV3(grupo) : NIL_UUID
|
||||||
|
|
@ -49,22 +126,5 @@ export const uuidV3 = (chave: unknown, grupo?: unknown): string => {
|
||||||
: typeof chave === "number"
|
: typeof chave === "number"
|
||||||
? String(chave)
|
? String(chave)
|
||||||
: JSON.stringify(chave)
|
: JSON.stringify(chave)
|
||||||
const hash = createHash("md5")
|
return formatarUuidV3(md5(namespace + input))
|
||||||
.update(namespace + input)
|
|
||||||
.digest("hex")
|
|
||||||
return formatarUuidV3(hash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gera um UUID v4 (aleatório, não determinístico).
|
|
||||||
*
|
|
||||||
* - Usa `crypto.randomUUID()` nativo do Node.js 20+.
|
|
||||||
* - Usado quando unicidade é necessária, mas não se exige que seja previsível.
|
|
||||||
*/
|
|
||||||
export const uuidV4 = (): string => randomUUID()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Esta variável será descontinuada em versões futuras.
|
|
||||||
* Use a função `uuidV4()` diretamente.
|
|
||||||
*/
|
|
||||||
export const uuid = uuidV4
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue