@anpdgovbr/shared-types
Version:
Biblioteca central de tipos TypeScript compartilhados para os projetos da ANPD (BETA)
291 lines (290 loc) • 8.36 kB
JavaScript
;
/**
* @fileoverview
* Type guards (guardas de tipo) para validação em runtime de interfaces do sistema.
*
* @remarks
* Type guards permitem verificar se um objeto implementa uma interface específica,
* fornecendo type narrowing para o TypeScript e validações seguras em runtime.
*
* @module base/type-guards
* @public
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isBaseEntity = isBaseEntity;
exports.isNamedEntity = isNamedEntity;
exports.isSoftDelete = isSoftDelete;
exports.isActive = isActive;
exports.isInactive = isInactive;
exports.isAuditContext = isAuditContext;
exports.isCorrelationIds = isCorrelationIds;
exports.isAuditedEntity = isAuditedEntity;
exports.isRecentlyCreated = isRecentlyCreated;
exports.isRecentlyUpdated = isRecentlyUpdated;
exports.isNonEmptyArray = isNonEmptyArray;
exports.isNonEmptyString = isNonEmptyString;
const uuid_type_1 = require("./uuid.type");
/**
* Verifica se um objeto é uma {@link BaseEntity} válida.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui a propriedade `id` com formato UUID v4 (string)
*
* @example
* ```typescript
* const obj = { id: "a3f4c8c2-0c21-4a32-9f3d-8b4e2d6f9a1b", nome: "Teste" }
* if (isBaseEntity(obj)) {
* console.log(obj.id) // TypeScript sabe que obj.id existe e é string compatível com UUID
* }
* ```
*/
function isBaseEntity(obj) {
return (typeof obj === "object" &&
obj !== null &&
"id" in obj &&
typeof obj.id === "string" &&
uuid_type_1.UUID_V4_PATTERN.test(obj.id));
}
/**
* Verifica se um objeto é uma {@link NamedEntity} válida.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui `id` UUID string e `nome` string
*
* @example
* ```typescript
* const obj = { id: "d1b3c1c4-55a2-4d3a-b0b1-9d97b2c5e4f6", nome: "João" }
* if (isNamedEntity(obj)) {
* console.log(obj.nome.toUpperCase()) // Type-safe
* }
* ```
*/
function isNamedEntity(obj) {
return (isBaseEntity(obj) &&
"nome" in obj &&
typeof obj.nome === "string");
}
/**
* Verifica se um objeto implementa {@link SoftDelete}.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui a propriedade `active` do tipo `boolean`
*
* @example
* ```typescript
* const obj = { active: true, exclusionDate: null }
* if (isSoftDelete(obj)) {
* console.log(obj.active ? "Ativo" : "Inativo")
* }
* ```
*/
function isSoftDelete(obj) {
return (typeof obj === "object" &&
obj !== null &&
"active" in obj &&
typeof obj.active === "boolean");
}
/**
* Verifica se uma entidade com soft delete está ativa.
*
* @param entity Entidade a ser verificada
* @returns `true` se `active === true`
*
* @remarks
* Este é um helper convenience que assume que a entidade já implementa SoftDelete.
* Use {@link isSoftDelete} se precisar verificar primeiro se o objeto implementa a interface.
*
* @example
* ```typescript
* const usuario: SoftDelete = { active: true }
* if (isActive(usuario)) {
* console.log("Usuário está ativo")
* }
* ```
*/
function isActive(entity) {
return entity.active === true;
}
/**
* Verifica se uma entidade com soft delete está inativa (deletada logicamente).
*
* @param entity Entidade a ser verificada
* @returns `true` se `active === false`
*
* @example
* ```typescript
* const usuario: SoftDelete = { active: false }
* if (isInactive(usuario)) {
* console.log("Usuário foi desativado")
* }
* ```
*/
function isInactive(entity) {
return entity.active === false;
}
/**
* Verifica se um objeto implementa {@link AuditContext}.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui pelo menos um campo de AuditContext
*
* @remarks
* Como todos os campos de AuditContext são opcionais, esta função verifica
* se pelo menos uma das propriedades esperadas está presente.
*
* @example
* ```typescript
* const ctx = { userId: "123", ip: "192.168.1.1" }
* if (isAuditContext(ctx)) {
* console.log(`Usuário: ${ctx.userId}`)
* }
* ```
*/
function isAuditContext(obj) {
if (typeof obj !== "object" || obj === null)
return false;
const hasAuditFields = "userId" in obj ||
"ip" in obj ||
"userAgent" in obj ||
"contexto" in obj ||
"requestId" in obj ||
"traceId" in obj;
return hasAuditFields;
}
/**
* Verifica se um objeto implementa {@link CorrelationIds}.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui pelo menos um campo de correlação
*
* @example
* ```typescript
* const ids = { requestId: "req-123", traceId: "trace-456" }
* if (isCorrelationIds(ids)) {
* console.log(`Request: ${ids.requestId}`)
* }
* ```
*/
function isCorrelationIds(obj) {
if (typeof obj !== "object" || obj === null)
return false;
const hasCorrelationFields = "requestId" in obj ||
"traceId" in obj ||
"spanId" in obj ||
"parentSpanId" in obj ||
"correlationId" in obj ||
"traceparent" in obj ||
"tracestate" in obj;
return hasCorrelationFields;
}
/**
* Verifica se um objeto implementa {@link AuditedEntity}.
*
* @param obj Objeto a ser verificado
* @returns `true` se o objeto possui `id`, `criadoEm` e/ou `atualizadoEm`
*
* @example
* ```typescript
* const entity = {
* id: "2a1f8c24-b5d7-4f0e-8f16-2c1d94ab2ed3",
* criadoEm: new Date(),
* atualizadoEm: new Date()
* }
* if (isAuditedEntity(entity)) {
* console.log(`Criado em: ${entity.criadoEm}`)
* }
* ```
*/
function isAuditedEntity(obj) {
if (!isBaseEntity(obj))
return false;
const hasAuditDates = ("criadoEm" in obj &&
(obj.criadoEm instanceof Date || obj.criadoEm === undefined)) ||
("atualizadoEm" in obj &&
(obj.atualizadoEm instanceof Date || obj.atualizadoEm === undefined));
return hasAuditDates;
}
/**
* Verifica se uma entidade foi criada recentemente (dentro de um período especificado).
*
* @param entity Entidade auditada
* @param hoursAgo Número de horas para considerar como "recente" (padrão: 24h)
* @returns `true` se a entidade foi criada dentro do período especificado
*
* @example
* ```typescript
* const entity: AuditedEntity = {
* id: "2a1f8c24-b5d7-4f0e-8f16-2c1d94ab2ed3",
* criadoEm: new Date()
* }
* if (isRecentlyCreated(entity, 1)) {
* console.log("Criado na última hora")
* }
* ```
*/
function isRecentlyCreated(entity, hoursAgo = 24) {
if (!entity.criadoEm)
return false;
const threshold = new Date();
threshold.setHours(threshold.getHours() - hoursAgo);
return entity.criadoEm >= threshold;
}
/**
* Verifica se uma entidade foi atualizada recentemente (dentro de um período especificado).
*
* @param entity Entidade auditada
* @param hoursAgo Número de horas para considerar como "recente" (padrão: 24h)
* @returns `true` se a entidade foi atualizada dentro do período especificado
*
* @example
* ```typescript
* const entity: AuditedEntity = {
* id: "2a1f8c24-b5d7-4f0e-8f16-2c1d94ab2ed3",
* atualizadoEm: new Date()
* }
* if (isRecentlyUpdated(entity, 2)) {
* console.log("Atualizado nas últimas 2 horas")
* }
* ```
*/
function isRecentlyUpdated(entity, hoursAgo = 24) {
if (!entity.atualizadoEm)
return false;
const threshold = new Date();
threshold.setHours(threshold.getHours() - hoursAgo);
return entity.atualizadoEm >= threshold;
}
/**
* Verifica se um valor é um array não vazio.
*
* @param value Valor a ser verificado
* @returns `true` se o valor é um array com pelo menos um elemento
*
* @example
* ```typescript
* const items = [1, 2, 3]
* if (isNonEmptyArray(items)) {
* console.log(`Primeiro item: ${items[0]}`)
* }
* ```
*/
function isNonEmptyArray(value) {
return Array.isArray(value) && value.length > 0;
}
/**
* Verifica se um valor é uma string não vazia.
*
* @param value Valor a ser verificado
* @returns `true` se o valor é uma string com pelo menos um caractere (após trim)
*
* @example
* ```typescript
* const nome = " João "
* if (isNonEmptyString(nome)) {
* console.log(nome.trim())
* }
* ```
*/
function isNonEmptyString(value) {
return typeof value === "string" && value.trim().length > 0;
}